STM8S+DS18B20+1Wire over UART - Dziwne zachowanie układu

Pozostałe układy mikrokontrolerów, układy peryferyjne i inne, nie mieszczące się w powyższych kategoriach.
Awatar użytkownika
ZbeeGin
User
User
Posty: 444
Rejestracja: sobota 08 lip 2017, 17:16
Lokalizacja: Śląsko-Zagłębiowska Metropolia
Kontaktowanie:

STM8S+DS18B20+1Wire over UART - Dziwne zachowanie układu

Postautor: ZbeeGin » sobota 24 paź 2020, 11:13

Piszę aplikację dwupunktowego termometru z wykorzystaniem STM8S105 (i biblioteki SPL) oraz dwóch czujników DS18B20.

Mam tu małą zagwozdkę, której nie potrafię sensownie wytłumaczyć. Otóż aplikacja działa i działa prawidłowo jeśli urządzenie zostanie uruchomione przez załączenie napięcia zasilania sieciowego (Układ posiada mały impulsowy zasilacz AC/DC dostarczający 12V oraz step-down dostarczający potem 5V). Oba czujniki zostaną wtedy znalezione na magistrali, ich adresy wpisane do DS18B20_ID_Table i z obu temperatura jest prawidłowo czytana.

Jednak przy opracowywaniu programu, gdy urządzenie ma zasilanie i zostanie ponownie zaprogramowane - z wprowadzeniem procesora w stan RESET na czas programowania, nagle jeden z czujników nie zwraca temperatury i nie można go zaadresować. Muszę urządzenie odłączyć od zasilania i włączyć ponownie.

Co dziwne, odkryłem iż w takim przypadku - czyli startu od RESETu - pierwszy czujnik "przesunie się" w tabeli DS18B20_ID_Table na drugą pozycję, drugi zaś będzie na pozycji trzeciej. Gdy zmodyfikuję kod, by korzystał z takiego ułożenia adresów czujników w tabeli to aplikacja będzie odczytywać czujniki poprawnie.

Takie zachowanie układu stawia pod znakiem zapytania uruchomienie systemu Watchdog. Gdyby doszło do resetu procesora w wyniku zawieszenia aplikacji układ nagle przestanie czytać jeden z czujników, a to byłoby niedopuszczalne.


Najistotniejszy fragment kodu z pliku "main.h" poniżej. W plikach "one_wire.h"/"one_wire.c" są procedury związane z realizacją magistrali 1-Wire przy wykorzystaniem dostępnego UARTu. Są to procedury zaczerpnięte z książki Tomka Francuza, przeportowane z AVR do STM8 i korzystają z kilku funkcji biblioteki SPL dla układów STM8.

Code: Select all


#include "one_wire.h"
#include <string.h>

/*****************************************************************************/
/* Zmienne globalne */
/*****************************************************************************/
/**
* @brief Zmienne przechowujące struktury danych z czujników DS18B20
*/
uint8_t DS18B20_ID_Current[8]; /* Bieżące ID czujnika w trakcie wyszukiwania */
uint8_t DS18B20_ID_Table[MAX_DS18B20_ID][7];
/* Tabela ID wykrytych czujników na magistrali */
int16_t DS18B20_RetValue; /* Wartość zwracana przez zaadresowany czujnik */
uint8_t DS18B20_Found; /* Liczba odnalezionych czujników */
uint8_t DS18B20_BitDiff = 0; /* Numer bitu różniącego się przy wyszukiwaniu */

/*****************************************************************************/
/* Funkcje konfiguracji */
/*****************************************************************************/

/**
* @brief Konfiguracja portów GPIO
* @param Brak
* @retval Brak
*/
static void STM8_GPIO_Setup(void)
{
(...)
/* Piny UART */
GPIO_Init(UART_PORT, TX_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(UART_PORT, RX_PIN, GPIO_MODE_IN_FL_NO_IT);
(...)
}

/*****************************************************************************/
/* Funkcje obsługi DS18B20 - by Tomasz Francuz */
/*****************************************************************************/
/**
* @brief Funkcja rozpoczynająca konwersję temperatury przez wszystkie
* układy DS18B20
* @param block : Wartość 0 wyłącza blokadę działania programu na
* czas konwersji. Wartość 1 włącza blokadę.
* @retval Brak
*/
static void DS18B20_Start_Conversion(uint8_t block)
{
/* Czy coś jest na magistrali */
if(OW_WaitForPresencePulse() == 0) return;
/* Jeśli tak to pomijamy polecenie MATCH ROM i wysyłamy od razu CONVERT T */
OW_Write(OW_SKIPROM);
OW_Write(OW_CONVERT);
/* Czy czekamy na odpowiedź? */
if(block) while(!OW_ReadBit());
}

/**
* @brief Funkcja odczytująca temperaturę z pamięci wybranego
* układu DS18B20
* @param aID : Wskaźnik na tablicę z numerem seryjnym
* adresowanego czujnika
* @retval Funkcja zwraca 16 bitową wartość temperatury
*/
static int16_t DS18B20_GetTemperature(uint8_t *aID)
{
uint16_t temp;

/* Adresujemy urządzenie i sprawdzamy czy odpowiada */
OW_SelectDevice(aID);
if(OW_GetError() != OW_OK) return 0xFFFF;

/* Czytamy zawartość pamięci czujnika i przeliczamy */
OW_Write(OW_READ_SCRATCHPAD);
temp = OW_Read();
temp = temp + (OW_Read() << 8);
/* Konwersja kodów - tylko wartości całkowite */
if(temp & 0x8000) temp = 1 - (temp ^ 0xFFFF);

return temp;
}

/*****************************************************************************/
/* Funkcje głównego programu */
/*****************************************************************************/
/**
* @brief Funkcja inicjalizacyjna programu
* @param Brak
* @retval Kod wyjścia - Brak
*/
static void SystemInit(void)
{
STM8_Clock_Setup();
STM8_GPIO_Setup();
STM8_TIM4_Setup();
STM8_TIM2_Setup();
enableInterrupts();

OW_Init();
(...)
/* Skanuj magistralę w poszukiwaniu czujników */
for(DS18B20_Found = 0; DS18B20_Found < MAX_DS18B20_ID; DS18B20_Found++) {
DelayMs(100);
OW_SetError(OW_OK);

/* Przeszukaj magistralę w poszukiwaniu unikalnych ID */
DS18B20_BitDiff = OW_Search(OW_SEARCHROM, DS18B20_ID_Current, DS18B20_BitDiff);
if(OW_GetError() != OW_OK) break;

/* Skopiuj zeskanowane ID do tabeli czujników */
memcpy(&DS18B20_ID_Table[DS18B20_Found][0], DS18B20_ID_Current, 7);

/* Jeśli nie ma już unikalnych ID to opuść pętlę */
if(DS18B20_BitDiff == 0) break;
}

/* Rozpocznij konwersję temperatury wszystkich czujników i zaczekaj na wynik */
DS18B20_Start_Conversion(1);
for(uint8_t idx = 0; idx <= DS18B20_Found; idx++) {

/* Odpytaj kolejno każdy czujnik z ID_Table i wprowadź dane do systemu */
DS18B20_RetValue = DS18B20_GetTemperature(&DS18B20_ID_Table[idx][0]);
switch(idx) {
case 0: Temperature.actual_t1 = (DS18B20_RetValue / 16); break;
case 1: Temperature.actual_t2 = (DS18B20_RetValue / 16); break;
default: break;
}
}
(...)
}

/*****************************************************************************/
/* Funkcja main programu */
/*****************************************************************************/
/**
* @brief Główna funkcja programu
* @param Brak
* @retval Kod wyjścia - Brak
*/
int main(void)
{
SystemInit();

while(1) {

/* Rozpocznij konwersję temperatury wszystkich czujników i zaczekaj na wynik */
DS18B20_Start_Conversion(1);
DelayMs(200);
for(uint8_t idx = 0; idx <= DS18B20_Found; idx++) {
/* Odpytaj kolejno każdy czujnik z ID_Table i wprowadź dane do systemu */
DS18B20_RetValue = DS18B20_GetTemperature(&DS18B20_ID_Table[idx][0]);
switch(idx) {
case 0: Temperature.actual_t1 = (DS18B20_RetValue / 16); break;
case 1: Temperature.actual_t2 = (DS18B20_RetValue / 16); break;
default: break;
}
}
(...)
}


Tu udało mi się uchwycić co się dzieje na magistrali po załączeniu zasilania. Z prawdopodobnym wskazaniem miejsc w kodzie.
1wire-good.jpg


A tu dziwne przebiegi po RESET. Nie rozpoznaję co tu się dzieje w stosunku do kodu. Prawdopodobnie źle to jest uchwycone.
1wire-bad.jpg
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Awatar użytkownika
xor
User
User
Posty: 168
Rejestracja: poniedziałek 05 wrz 2016, 21:44

Re: STM8S+DS18B20+1Wire over UART - Dziwne zachowanie układu

Postautor: xor » sobota 24 paź 2020, 14:22

uint8_t DS18B20_ID_Table[MAX_DS18B20_ID][7];

A dlaczego Id 7 bajtowy? OIMW Match ROM wymaga adresu 64 bitowego.
Ile bajtów OW_SelectDevice(aID) podaje na magistralę?
Co się pojawia w tablicy DS18B20_ID_Table po resecie?

Awatar użytkownika
ZbeeGin
User
User
Posty: 444
Rejestracja: sobota 08 lip 2017, 17:16
Lokalizacja: Śląsko-Zagłębiowska Metropolia
Kontaktowanie:

Re: STM8S+DS18B20+1Wire over UART - Dziwne zachowanie układu

Postautor: ZbeeGin » sobota 24 paź 2020, 17:13

Z tego co napisał TMF, użył tablicy 7 bajtów bo CRC jest i tak wyliczane oraz sprawdzane "on-fly". W OW_SelectDevice(aID) jest to tak zrobione i wypchane na magistralę jako ostatnie:

Code: Select all

/**
* @brief Funkcja wysyłająca ciąg danych służących do wybrania
* odpowiedniego urządzenia na magistrali 1-Wire
* @param aID : Wskaźnik do tablicy z numerem seryjnym urządzenia
* @retval Brak
*/
void OW_SelectDevice(const uint8_t *aID)
{
uint8_t crc = 0;

/* Sprawdź czy jakiekolwiek urządzenie odpowiada */
if(OW_WaitForPresencePulse() == FALSE) return;
/* Jeśli tak, to wysyłamy mu polecenie MATCH ROM */
OW_Write(OW_MATCHROM);
/* Oraz kolejne 8 bajtów danych zakończonych oblicznaym CRC */
for(uint8_t a = 0; a < 7; a++) {
crc = _crc_ibutton_update(crc, aID[a]);
OW_Write(aID[a]);
}
OW_Write(crc);
}



Co tam dokładnie jest w tablicy to nie wiem, bo w STM8 nie mam możliwości debugowania w układzie. Jedyny UART mam zajęty przez 1-Wire. :( A na pozostałych pinach wiszą inne peryferia - 100% wykorzystania.
Tablica powinna zawierać zera bo w sekcji inicjalizacji kompilator zeruje obszar zmiennych:

Code: Select all

;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
.area HOME
.area GSINIT
.area GSFINAL
.area GSINIT
__sdcc_gs_init_startup:
__sdcc_init_data:
; stm8_genXINIT() start
ldw x, #l_DATA
jreq 00002$
00001$:
clr (s_DATA - 1, x)
decw x
jrne 00001$
00002$:
ldw x, #l_INITIALIZER
jreq 00004$
00003$:
ld a, (s_INITIALIZER - 1, x)
ld (s_INITIALIZED - 1, x), a
decw x
jrne 00003$
00004$:
; stm8_genXINIT() end
.area GSFINAL
jp __sdcc_program_startup


Raczej nie ma opcji by program startował z innego miejsca przy RESET a innym przy załączeniu zasilania.

Awatar użytkownika
xor
User
User
Posty: 168
Rejestracja: poniedziałek 05 wrz 2016, 21:44

Re: STM8S+DS18B20+1Wire over UART - Dziwne zachowanie układu

Postautor: xor » niedziela 25 paź 2020, 09:32

ZbeeGin pisze:CRC jest i tak wyliczane oraz sprawdzane "on-fly".

OK. Jaki to ma sens? Tj. wyliczanie, bo że sprawdzanie to oczywiste.

ZbeeGin pisze:Tablica powinna zawierać zera

To wiadomo, ale co zawiera po przeszukaniu magistrali na pierwszej pozycji? Pisałeś, że czujniki przesuwają się w górę tablicy. Może tu by się dało znaleźć jakiś trop.
Wyglada jakby DS18B20_ID_Current albo DS18B20_BitDiff nie były po resecie inicjowane 0. Załaszcza podejrzana jest zmienna DS18B20_BitDiff bo inicjujesz ją zerem, czyli tak jakby po resecie nie wykonywała się inicjacja przypisań zmiennych. Po pierwszym obrocie pętli DS18B20_BitDiff jest jawnie ustawione na 0 i program już poprawnie wykrywa czujniki. Może spróbuj przed pętlą je wyzerować jawnie?

Awatar użytkownika
ZbeeGin
User
User
Posty: 444
Rejestracja: sobota 08 lip 2017, 17:16
Lokalizacja: Śląsko-Zagłębiowska Metropolia
Kontaktowanie:

Re: STM8S+DS18B20+1Wire over UART - Dziwne zachowanie układu

Postautor: ZbeeGin » niedziela 25 paź 2020, 11:09

xor pisze:Wyglada jakby DS18B20_ID_Current albo DS18B20_BitDiff nie były po resecie inicjowane 0.

Tak na szybko napisałem sobie kawałek kodu by korzystając z dostępnych dwóch wyświetlaczy 7 segmentowych wylistowało mi całą zawartość DS18B20_BitDiff, DS18B20_ID_Current, DS18B20_ID_Table. Wszystkie te zmienne po resecie jak i po starcie po odłączeniu zasilania wykazują zawartość zerową. Więc sekcja inicjalizacji robi co do niej należy w oby przypadkach.

Zobaczę czy uda mi się tak wpleść te procedury by wylistować również te same zmienne ale z podłączonymi czujnikami w obu przypadkach tuż po wykonaniu przeszukania magistrali. Tylko muszę poprawić procedury wyświetlania by mogły pokazywać wartości HEX.

Awatar użytkownika
piotrek
User
User
Posty: 131
Rejestracja: niedziela 05 lis 2017, 02:46

Re: STM8S+DS18B20+1Wire over UART - Dziwne zachowanie układu

Postautor: piotrek » niedziela 25 paź 2020, 11:40

Nie wiem jakiego kompilatora używasz, ale w dokumentacji RCSTM8.pdf znalazłem coś takiego:

z1.png


i zalecenie

z2.png


spróbuj wyzerować wszystkie zmienne w main na starcie
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Awatar użytkownika
ZbeeGin
User
User
Posty: 444
Rejestracja: sobota 08 lip 2017, 17:16
Lokalizacja: Śląsko-Zagłębiowska Metropolia
Kontaktowanie:

Re: STM8S+DS18B20+1Wire over UART - Dziwne zachowanie układu

Postautor: ZbeeGin » niedziela 25 paź 2020, 11:54

Używam SDCC w wersji 4.0.0 (Release).
Jak wykazuje mój dopisany kod kluczowe zmienne dla DS18B20 są zerowane przez kod inicjalizacyjny wygenerowany przez kompilator. Patrz moje poprzednie posty.

---
Mały update.
Mój kod do podglądu zmiennych wstawiłem w SystemInit() tuż po przeskanowaniu magistrali, przed rozpoczęciem pomiarów.

Przy uruchomieniu przez załączenie zasilania w zmiennych jest to:
00 - DS18B20_BitDiff
2881bd480c000027 - DS18B20_ID_Current
286c4f490c0000 - DS18B20_ID_Table[0]
2881bd480c0000 - DS18B20_ID_Table[1]
00000000000000 - DS18B20_ID_Table[2]
00000000000000 - DS18B20_ID_Table[3]

Zatem wyszukało dwa czujniki, umieściło ich numery seryjne w tablicy na właściwych pozycjach.
DS18B20_ID_Current zawiera numer drugiego czujnika - zgodnie z oczekiwaniami, bo był wyszukany jako ostatni.
CRC wyliczyło ok: https://crccalc.com/?crc=2881bd480c0000 ... uttype=hex
Program działa poprawnie.

A teraz uruchomienie ponowne przez wystawienie sygnału RESET:
00 - DS18B20_BitDiff
0000000000000000 - DS18B20_ID_Current
00000000000000 - DS18B20_ID_Table[0]
00000000000000 - DS18B20_ID_Table[1]
00000000000000 - DS18B20_ID_Table[2]
00000000000000 - DS18B20_ID_Table[3]

O dziwo tablica zawiera teraz same zera i program nie pokazuje w ogóle temperatur.
Prawdopodobnie dlatego, że w domu mam to sklecone na stykówce. Musiałbym jutro zweryfikować odczyt po RESET na gotowej płytce i czujnikach docelowych. Bo tam występował efekt jaki opisałem w pierwszym poście.

Nie zmienia to faktu, że program działa dobrze po zimnym starcie, a źle/w ogóle nie działa po RESET. :?

Awatar użytkownika
piotrek
User
User
Posty: 131
Rejestracja: niedziela 05 lis 2017, 02:46

Re: STM8S+DS18B20+1Wire over UART - Dziwne zachowanie układu

Postautor: piotrek » niedziela 25 paź 2020, 14:58

Ja bym wyodrębnił z kodu OW_Search do jakiejś funkcji testowej razem z SystemInit() i umieścił w pętli z delayem 1s. W szczególności interesujące jest czy DSy są prawidłowo inicjalizowane - sygnał reset (OW_Reset).
Poza tym - w jaki sposób zasilasz czujniki? dwoma przewodami czy trzema?

Wszystko wskazuje na to, że coś pamięta poprzedni stan sprzed resetu i tylko zanik napięcia powoduje prawidłową inicjalizację.
Inna przyczyna to w różnych adresach po resecie. Wektor sprzętowego resetu w ST8 skacze do 0x6000 gdzie jest bootloader. Inne źródła resetu powodują skok do 0x00 8004.

Awatar użytkownika
ZbeeGin
User
User
Posty: 444
Rejestracja: sobota 08 lip 2017, 17:16
Lokalizacja: Śląsko-Zagłębiowska Metropolia
Kontaktowanie:

Re: STM8S+DS18B20+1Wire over UART - Dziwne zachowanie układu

Postautor: ZbeeGin » niedziela 25 paź 2020, 15:28

Hmmm... Jeśli dopiszę fragment by pin TX przy starcie programu na prawie 100ms przeszedł w stan niski:

Code: Select all

(...)
/* Piny UART */
GPIO_Init(UART_PORT, TX_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
_delay_us(32000);
_delay_us(32000);
_delay_us(32000);
GPIO_Init(UART_PORT, TX_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(UART_PORT, RX_PIN, GPIO_MODE_IN_FL_NO_IT);

To program działa prawidłowo, nawet po wyzerowaniu procesora poprzez wymuszenie RESET (także podczas zwolnienia tej linii przez programator).

Usunięcie całkowicie tej konfiguracji pinów też powoduje, że program zaczyna działać prawidłowo. Lecz przy którymś tam zresetowaniu z kolei pierwotny problem znów się ujawnia.

piotrek pisze:Poza tym - w jaki sposób zasilasz czujniki? dwoma przewodami czy trzema?

Magistrala trzyprzewodowa bo będzie tam długa linia.

Awatar użytkownika
piotrek
User
User
Posty: 131
Rejestracja: niedziela 05 lis 2017, 02:46

Re: STM8S+DS18B20+1Wire over UART - Dziwne zachowanie układu

Postautor: piotrek » niedziela 25 paź 2020, 15:45

Myślę, że analiza inicjalizacji OW za pomocą oscyloskopu pomoże namierzyć problem. Może za słaba wydajność prądowa połączeń szyny zasilania? Chociaż to objawia się raczej w dwuprzewodowym interfejsie OW.


Wróć do „Inne mikroklocki, również peryferyjne”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 1 gość