plywakd 2 Napisano Styczeń 3, 2020 Udostępnij Napisano Styczeń 3, 2020 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 Cytuj Link to post Share on other sites
Anonim Styczeń 10, 2020 Udostępnij Styczeń 10, 2020 Wklej tu tekst programu za pomocą opcji "<>wstaw kod" bo mi się program do rozpakowywania zawiesza.. Cytuj Link to post Share on other sites
plywakd 2 Styczeń 10, 2020 Założyciel tematu Udostępnij Styczeń 10, 2020 /* 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 Cytuj Link to post Share on other sites
Anonim Styczeń 10, 2020 Udostępnij Styczeń 10, 2020 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. Cytuj Link to post Share on other sites
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Szukasz producenta PCB? Sprawdź firmę JLCPCB. Dlaczego warto? • Prototypy PCB 2-warstwowe za 2$ (gotowe w 24 godziny) • Prototypy PCB 4-warstwowe za 5$ • Montaż SMT od 7$ • Produkcja w profesjonalnej fabryce (zobacz film) Sprawdź też » Jak powstaje PCB? Wycieczka po fabryce
plywakd 2 Styczeń 23, 2020 Założyciel tematu Udostępnij Styczeń 23, 2020 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. 1 Cytuj Link to post Share on other sites
MaxiMeister11 0 Luty 20, 2020 Udostępnij Luty 20, 2020 @plywakd możesz pokazać cały projekt, zależy mi jak ustawiłeś timery, bo u mnie są błędy z komunikacja Cytuj Link to post Share on other sites
plywakd 2 Luty 22, 2020 Założyciel tematu Udostępnij Luty 22, 2020 @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 Cytuj Link to post Share on other sites
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. 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
Pomocna odpowiedź
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!