Skocz do zawartości
plywakd

[STM32] podłączenie czujnika temperatur DHT11

Pomocna odpowiedź

Witam, muszę zaimplementować odczyt temperatury z czujnika DHT11 poprzez STM32F103RB i wysyłać to poprzez USART(9600b/s). Korzystam z DWT_delay aby mieć opóźnienie w us do inicjalizacji DHT. Problem polega na tym, że mikroprocesor pobiera dane tylko raz i zawiesza się. USART obsługuje przerwania i jest zaimplementowany na buforze kołowym(piny domyślnie PA2-PA3). Dodatkowo mam wyświetlacz 7-segmentowy i docelowo chce na nim wyświetlać dane ( podpięcia PA0-PA1,PA4-PA8) z czujnika(PA9). Po resecie z watchdoga/czarnego buttona na nowo pobrane są dobre dane. W załączniku podsyłam program main z CubeIDE.

ProjectMain.zip

Udostępnij ten post


Link to post
Share on other sites

Wklej tu tekst programu za pomocą opcji "<>wstaw kod" bo mi się program do rozpakowywania zawiesza..

Udostępnij ten post


Link to post
Share on other sites
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "iwdg.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "dwt_delay.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
char buff[100];
uint16_t Rh,RhDec,Temp,TempDec,ChkSum;
uint8_t Rh_byte1, Rh_byte2, Temp_byte1, Temp_byte2;
uint16_t sum, RH, TEMP;
uint8_t check = 0;
uint8_t RX_Buf[255], RX_E=0, RX_B=0; //Receive array, RxBusy pointer, RxEmpty pointer
uint8_t TX_Buf[255], TX_E=0, TX_B=0;//Transmit array and Busy/empty pointer as in Receive
volatile int bufSize=255, comSize=63 , i=0, j= 0; //size of buffers RX,TX and command array, iterators to go through arrays
volatile int  time, timer;
uint8_t COM[63]; //COM as command array gets string from RX and parse them
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ //function handling interruption from HAL_UART_Receive_IT
	if(huart->Instance==USART2){ //check if interruption was from USART
		RX_E++; //move pointer to next byte
		if(RX_E>=bufSize) RX_E = 0; //check if empty pointer is out of scope of array and if is, assign 0
		HAL_UART_Receive_IT(&huart2,&RX_Buf[RX_E],1); //receive another byte and write in empty space
	}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){ //function handling interruption from HAL_UART_Transmit_IT
	if(huart->Instance==USART2){ //check if interruption was from USART
		if(TX_B!=TX_E){ //check if there's anything in buffer
			uint8_t tmp = TX_Buf[TX_B]; //temp variable to store first element in buffer
			TX_B++; //jmove pointer to next char
			if(TX_B>=bufSize) TX_E=0; //check if busy pointer is out of scope of array and if is, assign 0
			HAL_UART_Transmit_IT(&huart2,&tmp,1); //send another byte from first stored
		}
	}
}
/*-------------OBSłUGA WYSYłANIA-------------*/
void USART2_fsend(char* format, ...)
{
	char tmp_rs[128]; //tablica pomocnicza
	int i; //zmienna pomocnicza
	__IO int idx; //zmienna pomocnicza

	va_list arglist; //zmienna do obsługi formatowania argumentów przekazywanych w funkcji
	va_start(arglist,format);
	vsprintf(tmp_rs,format,arglist); //złożenie łańcucha z argumentami i przypisanie do tablicy pomocniczej
	va_end(arglist);

	idx=TX_E; //przypisanie do zmiennej pomocniczej wskaźnika empty z bufora wysyłania

	for(i=0;i<strlen(tmp_rs);i++) //przejście po elementach tablicy pomocniczej, które nie są puste
	{
		TX_Buf[idx]=tmp_rs[i]; //przypisanie elementowi bufora wysyłania wartości elementu z tablicy pomocniczej
		idx++; //zwiększenie zmiennej pomocniczej, wskazującej na element bufora wysyłania
		if(idx >= bufSize) idx=0; //jeżeli zmienna wyszła poza zakres bufora przesunięcie jej na początek
	}
	__disable_irq(); //wyłączenie zapytań o przerwania

	if((TX_E==TX_B)&&(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_TXE)==SET)) //jeżeli wskaźniki empty i busy są sobie równe oraz flaga bufora wysyłania jest ustawiona
	{
		TX_E=idx; //ustawienie zmiennej pomocniczej jako wskaźnik empty bufora wysyłania
		uint8_t tmp=TX_Buf[TX_B]; //przypisanie do zmiennej pomocniczej elementu, który ma zostać wysłany
		TX_B++; //zwiększenie wskaźnika busy
		if(TX_B >= bufSize) TX_B=0; //jeżeli wskaźnik busy wychodzi poza rozmiar bufora przesunięcie go na początek
		HAL_UART_Transmit_IT(&huart2, &tmp, 1); //wysłanie elementu przypisanego do zmiennej pomocniczej
	}
	else
	{
		TX_E=idx; //ustawienie zmiennej pomocniczej jako wskaźnik empty bufora wysyłania
	}
	__enable_irq(); //włączenie zapytań o przerwania
}//fsend
void parser(void) {
	if (RX_B != RX_E) { //check if there's message in buffer
		if(RX_Buf[RX_B] != ';') { //check if its end of command with semicolon
			COM[j] = RX_Buf[RX_B]; //assign char from recieve to command array
			j++; //move to another space in COM array
			if (j >= comSize) j = 0; //check if j pointer is out of scope of comSize and if is, assign 0
		}
		else {
			COM[j] = '\0'; //add to create string
			j = 0;
			if(strcmp(COM, "SET1") == 0) { //PARSE COMMAND
				GPIOA->ODR=0x0171;// Display 1
				USART2_fsend("Komenda poprawna!\n\r");
			} else if(strcmp(COM, "SET2") == 0) {
				GPIOA->ODR=0x00A0;// Display 2
				USART2_fsend("Komenda poprawna!\n\r");
			} else if(strcmp(COM, "TEMP") == 0) {
				USART2_fsend("Komenda poprawna!\n\r");
				USART2_fsend("TEMP ");
				sprintf(buff,"%d",Temp_byte1);
				USART2_fsend(buff);
			} else {
				USART2_fsend("ERR\n\r"); //return error if command cannot be parsed
			}
		}
		RX_B++; //move to next char to read from RX buffer
		if(RX_B >= bufSize) RX_B = 0;//check if busy pointer is out of scope of array and if is, assign 0
	}
}
void IWDG_Refresh(void) {
	/* Refresh IWDG: reload counter reset watchdoga*/
	if (HAL_IWDG_Refresh(&hiwdg) != HAL_OK) {

		/* Refresh Error */
		Error_Handler();
	}
}
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
#define DHT11_PORT GPIOA
#define DHT11_PIN GPIO_PIN_9
GPIO_InitTypeDef GPIO_InitStruct;
void set_gpio_output (void)
{
	/*Configure GPIO pin output: PA9 */
  GPIO_InitStruct.Pin = DHT11_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(DHT11_PORT, &GPIO_InitStruct);
}

void set_gpio_input (void)
{
	/*Configure GPIO pin input: PA9 */
  GPIO_InitStruct.Pin = DHT11_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(DHT11_PORT, &GPIO_InitStruct);
}

void DHT11_start(void){
	set_gpio_output();
	HAL_GPIO_WritePin(DHT11_PORT,DHT11_PIN,0);
	DWT_Delay(18000);
	set_gpio_input();
}
void check_response(void){
	DWT_Delay(40);
	if(!HAL_GPIO_ReadPin(DHT11_PORT,DHT11_PIN)){
		DWT_Delay(80);
		if((HAL_GPIO_ReadPin(DHT11_PORT,DHT11_PIN))) check=1;
		else check=0;
	}
	while((HAL_GPIO_ReadPin(DHT11_PORT,DHT11_PIN)));//wait for pin to go low
}
uint8_t read_data (void)
{
	uint8_t i,j;
	for (j=0;j<8;j++)
	{
		while (!(HAL_GPIO_ReadPin(DHT11_PORT,DHT11_PIN)));   // wait for the pin to go high
		DWT_Delay (40);   // wait for 40 us to get pin state
		if ((HAL_GPIO_ReadPin(DHT11_PORT,DHT11_PIN))==0)   // if the pin is low
		{
			i&= ~(1<<(7-j));   // write 0
		}
		else i|= (1<<(7-j));  // if the pin is high, write 1
		while ((HAL_GPIO_ReadPin (DHT11_PORT, DHT11_PIN)));  // wait for the pin to go low
	}
	return i;
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* 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_USART2_UART_Init();
  MX_IWDG_Init();
  /* USER CODE BEGIN 2 */
  DWT_Init();
  timer=HAL_GetTick();
  HAL_GPIO_WritePin(GPIOC,D1_Pin|D2_Pin|D3_Pin,GPIO_PIN_SET);//turn on digits on display
  USART2_fsend("Hello, I am STM32 !!!\n\r");//start message
  HAL_UART_Receive_IT(&huart2, &RX_Buf[RX_E], 1); //start listening on USART port
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  //parser();
	  //if(HAL_GetTick()-timer>1000){
	  	  DHT11_start ();
	  	  check_response ();
	  	  Rh_byte1 = read_data ();
	  	  Rh_byte2 = read_data ();
	  	  Temp_byte1 = read_data ();
	  	  Temp_byte2 = read_data ();
	  	  sum = read_data();
	  	  if(sum==(Rh_byte1+Rh_byte2+Temp_byte1+Temp_byte2)){
	  		USART2_fsend("TEMP ");
	  		sprintf(buff,"%d",Temp_byte1);
	  		USART2_fsend(buff);
	  		USART2_fsend("HUM: ");
	  		sprintf(buff,"%d",Rh_byte1);
	  		USART2_fsend(buff);
	  	  }
	  	  else {
	  		USART2_fsend("TEMP NAN");
	  	  }
	  	  HAL_Delay(1000);
	  	  IWDG_Refresh();
		  //timer=HAL_GetTick();
	  //}
  }
  /* USER CODE END 3 */
}

Załącznik z kodu

Udostępnij ten post


Link to post
Share on other sites

Na pierwszy rzut oka nie widzę nic drastycznego ale i czasu nie ma w tej chwili na szczegółową analizę.

Sprawdź samą funkcjonalność czyli wywal z projektu tymczasowo bufor usarta i wysyłaj/odbieraj dane przez polling. Nie wiem też co jest w "dwt_delay.h" może jakiś konflikt. Zostaw w projekcie tylko usart na pollingu z buforem liniowym i obsługę DHT jeśli zadziała to będzie wiadomo gdzie szukać błędu. A debuger gdzie się zatrzymuje? hard fault?

Od siebie dodam tylko, że przy transakcjach tekstowych lepiej jest używać funkcji std printf z nadpisaną funkcją int _write(...); int _read(...); w ciało której trzeba wstawić funkcje HAL_UART_ ...  zamiast motać dokoła z funkcjami ze zmienną ilością arg, wbudowana printf jest lepsza. Wystarczy podmienić bufor na własny w stdout i stdin albo przekierować na własny stream a do analizy komend można użyć funkcji z string.h. Pozdrawiam.

Udostępnij ten post


Link to post
Share on other sites

Problem rozwiązany, okazało się że pętla zawiesza się na drugim podejściu przy check_response na ostatniej pętli while. Wystarczyło zwiększyć w pętli głównej programu Delay na 1200 i czujnik odpowiada bezproblemowo.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@MaxiMeister11 Nie działałem na timerach, a jedynie robiłem odczytanie w pętli głównej co 1200 ms, robiłem to na różnicy tick-ów poprzez HAL_GetTick(). Timer przed pętlą główną =HAL_GetTick() i potem sprawdzasz w pętli czy aktualny HAL - timer >1200, jak tak to pobiera od czujnika informacje

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...