| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 | #include "common_config.h"#include "stm32f4xx.h"#include "gpio.h"#include "AM2301.h"#ifdef PRINTF_STDLIB#include <stdio.h>#endif#ifdef PRINTF_CUSTOM#include "tinystdio.h"#endif#include "FreeRTOS.h"#include "task.h"#include "semphr.h"#define AM2301_ERRORS_LIMIT    5/* Force remove debug output */#undef DBG#define DBG if(0)static void one_wire_delay_us(uint16_t time);static void am2301_pin_as_output(at2301_sensor *sensor);static void am2301_pin_as_input(at2301_sensor *sensor);AM2301_t am2301_reset(at2301_sensor *sensor);at2301_data_t sAM2301Sensorsdata[MAX_T_SENSORS];at2301_sensor sAM2301Sensors[MAX_T_SENSORS];TIM_TypeDef *timer = TIM2;static bool dht_present = false;static bool dht_finish = false;static bool new_hum_request = false;static uint8_t rawData[50];static void am2301_pin_as_output(at2301_sensor *sensor) {	gpio_pindef_t *pin = &gpio_pins[sensor->ow_pin];    gpio_hw_config_pin(pin->port, pin->pin, (GPIO_MODE_OUT_CFG | GPIO_SPEED_HIGH_CFG));    gpio_set(sensor->ow_pin, GPIO_SET);}static void am2301_pin_as_input(at2301_sensor *sensor) {  gpio_pindef_t *pin = &gpio_pins[sensor->ow_pin];    gpio_hw_config_pin(pin->port, pin->pin, (GPIO_MODE_IN_CFG | GPIO_PU_CFG));}AM2301_t am2301_reset(at2301_sensor *sensor){    uint8_t flag_err = 0;	new_hum_request = true;        /* Запрос данных у датчика */	//Перевод пина "на выход"	am2301_pin_as_output(sensor);	//Опускание линии данных на 500 мкс	gpio_set(sensor->ow_pin, 0);	one_wire_delay_us(500);	//Подъём линии, перевод порта "на вход"	gpio_set(sensor->ow_pin, 1);	am2301_pin_as_input(sensor);	for(uint8_t i = 0; i < 120; i++);	NVIC_EnableIRQ(sensor->irq);	flag_err = 0;	while(!dht_present) {		vTaskDelay(1);		flag_err ++;		if(flag_err > 5) {			break;		}	}	if (flag_err > 5) {		DBG printf("CONNECT ERR\r\n\r\n");		return CONNECTION_ERR;	}    return CONNECTION_OK;}AM2301_t am2301_get_data(at2301_sensor *sensor, at2301_data_t *data) {	uint8_t flag_err = 0;	dht_present = false;	dht_finish = false;	if (am2301_reset(sensor) != CONNECTION_OK) {		dht_present = false;		dht_finish = false;		NVIC_DisableIRQ(sensor->irq);        return CONNECTION_ERR;    }	flag_err = 0;	while(!dht_finish) {		vTaskDelay(1);		if(flag_err > 5) {			break;		}		flag_err ++;	}	if (flag_err > 5) {		dht_present = false;		dht_finish = false;		NVIC_DisableIRQ(sensor->irq);		return READ_ERR;	}	dht_present = false;	dht_finish = false;	NVIC_DisableIRQ(sensor->irq);	uint8_t data_sensor[5] = {0, 0, 0, 0, 0};	for(uint8_t a = 0; a < 5; a++) {		for(uint8_t b = 0; b < 8;  b ++) {			if(rawData[a*8 + b] > 100) data_sensor[a] |= (1<<(7 - b));		}	}	memset(rawData, 0, sizeof(rawData));	/* Проверка целостности данных */	if((uint8_t)(data_sensor[0] + data_sensor[1] + data_sensor[2] + data_sensor[3]) == data_sensor[4]) {		//Если контрольная сумма совпадает, то конвертация и возврат полученных значений		data->hum = (float)(((uint16_t)data_sensor[0]<<8) | data_sensor[1])*0.1f;		//Проверка на отрицательность температуры		if(!(rawData[2] & (1<<7))) {			data->temp = (float)(((uint16_t)data_sensor[2]<<8) | data_sensor[3])*0.1f;		}	else {			rawData[2] &= ~(1<<7);			data->temp = (float)(((uint16_t)data_sensor[2]<<8) | data_sensor[3])*-0.1f;		}	} else {		DBG printf("TEMP ERR\r\n\r\n");		return PARITY_ERR;	}	DBG printf("TEMP = %.1f\r\n\r\n", data->temp);	DBG printf("HUM = %.1f\r\n\r\n", data->hum);	return DATA_OK;	}void am2301_init_port(void){	 // Setup clock    if (timer == TIM2)        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);    else if (timer == TIM3)        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);    else        while(1){} // not implemented	TIM_TimeBaseInitTypeDef TIM_InitStructure;    TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;    TIM_InitStructure.TIM_Prescaler = 84 - 1; // For 84 MHz APB1 timer clock    TIM_InitStructure.TIM_Period = 0xFFFF;    TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;    TIM_InitStructure.TIM_RepetitionCounter = 0;    TIM_TimeBaseInit(timer, &TIM_InitStructure);    //TIM_ITConfig(timer, TIM_IT_Update, ENABLE);    TIM_Cmd(timer, ENABLE);	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);	// Selects the GPIOA pin 0 used as external interrupt source    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);	// Selects the GPIOC pin 12 used as external interrupt source    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource12);    // External interrupt settings    EXTI_InitTypeDef EXTI_InitStruct;    EXTI_InitStruct.EXTI_Line = EXTI_Line0 | EXTI_Line12;    EXTI_InitStruct.EXTI_LineCmd = ENABLE;    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;    EXTI_Init(&EXTI_InitStruct);    // Nested vectored interrupt settings    NVIC_InitTypeDef NVIC_InitStruct;    NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn | EXTI15_10_IRQn;    NVIC_InitStruct.NVIC_IRQChannelCmd = DISABLE;    // EXTI0_IRQn has Most important interrupt    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;    NVIC_Init(&NVIC_InitStruct);}void am2301_init_sensors(void){	uint8_t i;	for (i = 0; i < MAX_T_SENSORS; i++) {		sAM2301Sensorsdata[i].hum  = 0.0;		sAM2301Sensorsdata[i].temp  = 0.0;    	sAM2301Sensorsdata[i].ErrorCycle   = 0;    	sAM2301Sensorsdata[i].SensorState  = 1;  // По умолчанию устанавливаем признак неисправности	}	sAM2301Sensors[0].ow_pin = WDATA1;	sAM2301Sensors[0].irq = EXTI0_IRQn;	sAM2301Sensors[1].ow_pin = WDATA2;	sAM2301Sensors[1].irq = EXTI15_10_IRQn;}/**  * @brief  Задача чтения температуры 1-wire  */void vTaskDHT(void *pvParameters){  	(void)pvParameters;  		am2301_init_port();	am2301_init_sensors();	vTaskDelay(1000);	for (;;)	{		for(uint8_t i = 0; i < MAX_T_SENSORS; i++) {			if (am2301_get_data(&sAM2301Sensors[i], &sAM2301Sensorsdata[i]) != DATA_OK) {				sAM2301Sensorsdata[i].ErrorCycle ++;			} else {				sAM2301Sensorsdata[i].ErrorCycle = 0;				sAM2301Sensorsdata[i].SensorState = 0;			}			if (sAM2301Sensorsdata[i].ErrorCycle == AM2301_ERRORS_LIMIT) {				sAM2301Sensorsdata[i].SensorState = 1;				sAM2301Sensorsdata[i].ErrorCycle = 0;			}		}		vTaskDelay(2000);	}}void DHT_Task_Init(void) {    xTaskCreate(vTaskDHT, "vTaskDHT", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);}void TIM2_IRQHandler(void){    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);   // gpio_invert_output(LED_GREEN);}void one_wire_delay_us(uint16_t time) {    timer->CNT = 0;    time -= 1;    while (timer->CNT <= time) {        ;    }} void EXTI_IRQHandler(void){    static bool start_meas = false;	static uint8_t cnt_bit = 0;	// Checks whether the interrupt from EXTI0 or not    if (EXTI_GetITStatus(EXTI_Line0) || EXTI_GetITStatus(EXTI_Line12))    {       if(!dht_present) {		   cnt_bit = 0;		   if(new_hum_request) {			   start_meas = false;			   new_hum_request = false;		   }		   if (!start_meas) {			   timer->CNT = 0;			   start_meas = true;		   } else {			   if (timer->CNT >= 120){					dht_present = true;				  	start_meas = false;				  	timer->CNT = 0;			   }		   }		   	   } else {			rawData[cnt_bit++] = timer->CNT;			   			if (cnt_bit == 40){				dht_finish = true;			}			timer->CNT = 0;	   }                // Clears the EXTI line pending bit		EXTI_ClearITPendingBit(EXTI_Line0);        EXTI_ClearITPendingBit(EXTI_Line12);    }}
 |