STM32F1x + DHT22

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Аватара пользователя
Jman
Мучитель микросхем
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря
Контактная информация:

STM32F1x + DHT22

Сообщение Jman »

Добрый день всем! Есть проблема с работой датчика DHT22. Я пытаюсь использовать стороннюю библиотеку и выводить все в порт или на LCD. Код библиотеки (ногодрыг)
Спойлер

Код: Выделить всё

#include <stm32f10x_rcc.h>
#include <stm32f10x_gpio.h>
#include "delay.h"
#include "dht22.h"


uint16_t bits[40];

uint8_t  hMSB = 0;
uint8_t  hLSB = 0;
uint8_t  tMSB = 0;
uint8_t  tLSB = 0;
uint8_t  parity_rcv = 0;

static GPIO_InitTypeDef PORT;


void DHT22_Init(void) {
	RCC_APB2PeriphClockCmd(DHT22_GPIO_CLOCK,ENABLE);
	PORT.GPIO_Mode = GPIO_Mode_Out_PP;
	PORT.GPIO_Pin = DHT22_GPIO_PIN;
	PORT.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(DHT22_GPIO_PORT,&PORT);
}

uint32_t DHT22_GetReadings(void) {
	uint32_t wait;
	uint8_t i;

	// Generate start impulse for sensor
	DHT22_GPIO_PORT->BRR = DHT22_GPIO_PIN; // Pull down SDA (Bit_SET)
	Delay_ms(2); // Host start signal at least 800us
	DHT22_GPIO_PORT->BSRR = DHT22_GPIO_PIN; // Release SDA (Bit_RESET)

	// Switch pin to input with Pull-Up
	PORT.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_Init(DHT22_GPIO_PORT,&PORT);

	// Wait for AM2302 to start communicate
	wait = 0;
	while ((DHT22_GPIO_PORT->IDR & DHT22_GPIO_PIN) && (wait++ < 200)) Delay_us(2);
	if (wait > 50) return DHT22_RCV_NO_RESPONSE;

	// Check ACK strobe from sensor
	wait = 0;
	while (!(DHT22_GPIO_PORT->IDR & DHT22_GPIO_PIN) && (wait++ < 100)) Delay_us(1);
	if ((wait < 8) || (wait > 15)) return DHT22_RCV_BAD_ACK1;

	wait = 0;
	while ((DHT22_GPIO_PORT->IDR & DHT22_GPIO_PIN) && (wait++ < 100)) Delay_us(1);
	if ((wait < 8) || (wait > 15)) return DHT22_RCV_BAD_ACK2;

	// ACK strobe received --> receive 40 bits
	i = 0;
	while (i < 40) {
		// Measure bit start impulse (T_low = 50us)
		wait = 0;
		while (!(DHT22_GPIO_PORT->IDR & DHT22_GPIO_PIN) && (wait++ < 20)) Delay_us(1);
		if (wait > 16) {
			// invalid bit start impulse length
			bits[i] = 0xffff;
			while ((DHT22_GPIO_PORT->IDR & DHT22_GPIO_PIN) && (wait++ < 20)) Delay_us(1);
		} else {
			// Measure bit impulse length (T_h0 = 25us, T_h1 = 70us)
			wait = 0;
			while ((DHT22_GPIO_PORT->IDR & DHT22_GPIO_PIN) && (wait++ < 20)) Delay_us(1);
			bits[i] = (wait < 16) ? wait : 0xffff;
		}

		i++;
	}

	for (i = 0; i < 40; i++) if (bits[i] == 0xffff) return DHT22_RCV_RCV_TIMEOUT;

	return DHT22_RCV_OK;
}

uint16_t DHT22_DecodeReadings(void) {
	uint8_t parity;
	uint8_t  i = 0;

	hMSB = 0;
	for (; i < 8; i++) {
		hMSB <<= 1;
		if (bits[i] > 7) hMSB |= 1;
	}
	hLSB = 0;
	for (; i < 16; i++) {
		hLSB <<= 1;
		if (bits[i] > 7) hLSB |= 1;
	}
	tMSB = 0;
	for (; i < 24; i++) {
		tMSB <<= 1;
		if (bits[i] > 7) tMSB |= 1;
	}
	tLSB = 0;
	for (; i < 32; i++) {
		tLSB <<= 1;
		if (bits[i] > 7) tLSB |= 1;
	}
	for (; i < 40; i++) {
		parity_rcv <<= 1;
		if (bits[i] > 7) parity_rcv |= 1;
	}

	parity  = hMSB + hLSB + tMSB + tLSB;

	return (parity_rcv << 8) | parity;
}

uint16_t DHT22_GetHumidity(void) {
	return (hMSB << 8) + hLSB;
}

uint16_t DHT22_GetTemperature(void) {
	return (tMSB << 8) + tLSB;
}

Либа задержек
Спойлер

Код: Выделить всё

#include <stm32f10x_rcc.h>
#include "delay.h"

// SysTick interrupt handler
void SysTick_Handler() {
	
	if (TimingDelay != 0) { TimingDelay--; }
}

// Do delay for mSecs milliseconds
void Delay_ms(uint32_t mSecs) {
	SysTick_Config(SystemCoreClock / DELAY_TICK_FREQUENCY_MS);
	TimingDelay = mSecs+1;
	while (TimingDelay != 0);
}

// Do delay for nSecs microseconds
void Delay_us(uint32_t uSecs) {
	SysTick_Config(SystemCoreClock / DELAY_TICK_FREQUENCY_US);
	TimingDelay = uSecs+1;
	while (TimingDelay != 0);
}

В мейн все инициализирую и пытаюсь работать с датчиком.
Спойлер

Код: Выделить всё

int main(void)
{
	//SysTick_Config(SystemCoreClock / 1000);
	
	UART_Init();
	UART_SendStr("\nSTM32VLDiscovery is online.\n");

	while (1) {
		DHT22_Init();
		response = DHT22_GetReadings();
		if (response != DHT22_RCV_OK) {
			UART_SendStr("DHT22_GetReadings() error = ");
			UART_SendInt(response); UART_SendChar('\n');
		} else {
			response = DHT22_DecodeReadings();
			UART_SendStr("Parity: Received = "); UART_SendInt(response & 0xff);
			UART_SendStr(" Actual = "); UART_SendInt(response >> 8);
			UART_SendChar('\n');
			if ((response & 0xff) != (response >> 8)) {
				UART_SendStr("Wrong data received.\n");
			} else {
				temperature = DHT22_GetTemperature();
				humidity = DHT22_GetHumidity();

				UART_SendStr("Humidity: ");
				UART_SendInt(humidity / 10); UART_SendChar('.');
				UART_SendInt(humidity % 10); UART_SendStr("%RH");
				UART_SendChar('\n');
				UART_SendStr("Temperature: ");
				if ((temperature & 0x8000) != 0) UART_SendChar('-');
				UART_SendInt((temperature & 0x7fff) / 10); UART_SendChar('.');
				UART_SendInt((temperature & 0x7fff) % 10); UART_SendStr("C");
				UART_SendChar('\n');
			}
		}

		Delay_ms(1000);
	}
}
Дохожу до response = DHT22_GetReadings(); И тут происходит какое-то зацикливание, если я правильно понимаю. Все что ниже, больше не работает. Хоть в порт пиши, хоть на экран выводи, хоть ножкой дрыгай. В отладчике тоже до этого места доходит, захожу во внутрь функции DHT22_GetReadings(); и на первом же цикле застреваю. По идее, если бы не было ответа, я бы получил соответствующее предупреждение в терминале. В чем может быть проблема. Заранее благодарен за ответ и любую помощь!
Использую Keil uVision и VLDiscovery + DHT22 ()
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Реклама
Аватара пользователя
AlanDrakes
Прорезались зубы
Сообщения: 236
Зарегистрирован: Пн июл 04, 2016 16:51:22
Откуда: Россия, Омск

Re: STM32F1x + DHT22

Сообщение AlanDrakes »

У меня работает вот так.
Вообще БЕЗ библиотек.

Спойлер

Код: Выделить всё


console_put - вывод строки.
console_put_* - вывод чего-либо ещё строкой.
console_put_hex - выведет байт в виде FF
Можете заменить на printf или что-то подобное.

void DWT_Init(void) {
	//разрешаем использовать счётчик
	CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
	// Разблокировка регистров
	DWT->LAR = 0xC5ACCE55;
	//обнуляем значение счётного регистра
	DWT->CYCCNT = 0;
	//запускаем счётчик
	DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
};
static __inline uint32_t delta(uint32_t t0, uint32_t t1) {
	return (t1 - t0); 
};
void delay_us(uint32_t us) {
	uint32_t t0 = DWT->CYCCNT;
	uint32_t us_count_tic = us * (SystemCoreClock/1000000);
	while (delta(t0, DWT->CYCCNT) < us_count_tic) ;
};
/* void delay_ms(uint32_t ms) {
	uint32_t ms_now = tick_count;
	while ((ms_now + ms) > tick_count) {
		__WFI();
	};
}; */
void delay_ms(uint32_t ms) {
	uint32_t i=ms;
	while (i--) {
		delay_us(1000);
	};
};

// Где-то в дебрях main()
uint8_t th[5];
uint32_t i, j;

// 	console_put("Searching DHT22\r\n");
	GPIOB->BSRR = GPIO_BSRR_BR_2;	// Select Flash
	delay_ms(1);
	GPIOB->BSRR = GPIO_BSRR_BS_2;	// DeSelect Flash
	delay_us(25);
	GPIOB->BSRR = GPIO_BSRR_BR_2;	// Select Flash
	delay_us(1);
	GPIOB->MODER &= 0xFFFFFFCF;	// GPIOB[2] -> Input
	j = 0;
	for (i=0;i<100;i++) {
		if ((GPIOB->IDR & GPIO_IDR_IDR_2) == 0) {
// 			console_put("DHT22 detected\r\n");
			j = 1;
			break;
		};
		delay_us(5);
	};
	while(((GPIOB->IDR & GPIO_IDR_IDR_2) == 0));
	while((GPIOB->IDR & GPIO_IDR_IDR_2));
	if (j) {
		for (v=0;v<40;v++) {
			while(((GPIOB->IDR & GPIO_IDR_IDR_2) == 0)) { delay_us(1); };
			j = 0;
			while((GPIOB->IDR & GPIO_IDR_IDR_2)) { j++; delay_us(1); };
			if (j > 40) {
				th[((v)>>3)] |= (0x80 >> (v & 0x07));
			} else {
			};
		};
	};
// 	console_put("Data read done.");
// 	for (i=0;i<5;i++) {
// 		console_put_hex_byte(th[i]);
// 	};
// 	console_put("\r\n");
	i = th[0] + th[1] + th[2] + th[3];
	i = i & 0xFF;
	if (i == th[4]) {
// 		console_put("CRC OK\r\n");
		console_put("RH: ");
		console_put_int((th[0] * 256 + th[1]) / 10);
		console_put(".");
		console_put_int((th[0] * 256 + th[1]) % 10);
		console_put("%\tTemp: ");
		console_put_int((th[2] * 256 + th[3]) / 10);
		console_put(".");
		console_put_int((th[2] * 256 + th[3]) % 10);
		console_put("C\r\n");
	} else {
		console_put("CRC ERROR\r\n");
	};
Реклама
Ответить

Вернуться в «ARM»