Skocz do zawartości

[STM32] podłączenie czujnika temperatur DHT11


plywakd

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

Link do komentarza
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

Link do komentarza
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.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

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
Link do komentarza
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

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.