Skocz do zawartości

STM32, union, nieprawidłowe przypisywanie zmiennych


_ImPuLs_

Pomocna odpowiedź

Proszę o pomoc w związku z używaniem 'union' w środowisku STM32CubeIDE, bo nie działa mi tak jak powinno wg mnie.

Mam taki kod:

	union DaneWiersza1{
		bool wiersz1data[80];
		uint8_t wiersz1bajt[10];
	}UniaWiersz1;

int main(void)
{

  while (1)
  {

  	UniaWiersz1.wiersz1data[78]) = 1;
  	UniaWiersz1.wiersz1data[79]) = 1;
    
	UniaWiersz1.wiersz1bajt[2] = 0;
	UniaWiersz1.wiersz1bajt[3] = 1;
	UniaWiersz1.wiersz1bajt[4] = 2;
	UniaWiersz1.wiersz1bajt[5] = 255;
  }
}

Prawidłowo działa przypisywanie do danych 'bool'

  	UniaWiersz1.wiersz1data[78]) = 1;
  	UniaWiersz1.wiersz1data[79]) = 1;

Z linii następnych

	UniaWiersz1.wiersz1bajt[2] = 0;
	UniaWiersz1.wiersz1bajt[3] = 1;
	UniaWiersz1.wiersz1bajt[4] = 2;
	UniaWiersz1.wiersz1bajt[5] = 255;

prawidłowo nie działa żadna.

Jedynie linia

UniaWiersz1.wiersz1bajt[3] = 1;

powoduje wpisanie wartości równej '1' ale nie do trzeciego bajtu, tylko do trzeciego bitu w ciągu tak jakby to było wydane polecenie

UniaWiersz1.wiersz1data[3] = 1;

 

W czym może być problem ?

 

 

Link do komentarza
Share on other sites

Problem jest w tym, że bool nie jest przechowywane w jednym bicie, więc 
 

bool wiersz1data[80];
uint8_t wiersz1bajt[10];

Mają różne rozmiary, dalej nie patrzyłem co robisz bo tu jest grzech pierworodny Twojego kodu.

  • Pomogłeś! 1
Link do komentarza
Share on other sites

@_ImPuLs_ Tak dla zrozumienia co się dzieje, spróbuj zrobić unię z pól o różnych (prostych) typach i zobacz co będzie gdy wstawisz wartość do któregoś pola - odczytaj po kolei wszystkie pola i zobacz co zawierają po takim jednorazowym wpisie.

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Możesz też tak kombinować (cout pomiń, jest do wypisywania w konsoli).

#include <iostream>
#include <cstdint>
using namespace std;

union dane_wiersza {
	struct { uint8_t _8: 1, _7: 1, _6: 1, _5: 1, _4: 1, _3: 1, _2: 1, _1: 1; } bity[10]; // bity oznaczone indeksami 1-8
	uint8_t bajty[10]; // uint8_t = 1 bajt
} typedef dw;

int main() {
	dw x = {};
	
	// wrzuca znaki a-j
	for(uint8_t i = 0; i < 10; i++) x.bajty[i] = 97 + i;
	
	// wyświetla znaki przed zmianą: "abcdefghij"
	cout << "Przed:\t";
	for(uint8_t i = 0; i < 10; i++) cout << x.bajty[i];
	cout << endl;
	
	// zamienia czwarty bit w ostatnim bajcie z 0 na 1 (0110 1010 -> 0111 1010), czyli wyświetla "z" zamiast "j" 
	x.bity[9]._4 = 1;
	
	// wyświetla znaki po zmianie
	cout << "Po:\t";
	for(uint8_t i = 0; i < 10; i++) cout << x.bajty[i];
	cout << endl;
	
	return 0;
}

 

  • Pomogłeś! 1
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

@orb777 O coś takiego mi właśnie chodziło.
Zapewne nie jest to eleganckie rozwiązanie, ale na początek mi w zupełności wystarczy.

Jak moje wiedza będzie na wyższym poziomie to pewnie znajdzie się na to jeszcze inny, lepszy sposób.

Dziękuję za pomoc i wskazówki.

 

Link do komentarza
Share on other sites

@_ImPuLs_ , w takim razie poszukaj info o operacjach bitowych, przesunięciach, maskach, itd. Metoda z union-struct jest prostsza w zrozumieniu. Jako amator też wracam do tematu po latach i np. operacje bitowe wypada lepiej przewertować.

Ogólne dla zabawy różnie możesz sobie pokombinować, np. za pomocą struktury i rzutowania wskaźnika, żeby pokazywał na inny typ.

#include <iostream>
#include <cstdint>
using namespace std;

// odwróciłem kolejność bitów; teraz zaczynaja się od 0 tak jak na zdjęciu z kalkulatora
struct bajt_na_bity { uint8_t _0: 1, _1: 1, _2: 1, _3: 1, _4: 1, _5: 1, _6: 1, _7: 1; } typedef bb; 

int main() {
	int liczba = 0; // na starcie 0
	bb * wsk = reinterpret_cast<bb *>(&liczba); // rzutowanie; wskaźnik do struktury pokazuje miejsce w pamięci gdzie jest pierwszy bajt int-a "liczba"
	
	cout << "Rozmiar int: " << sizeof(int) << " bajty\n"; // u mnie 4 bajty, więc ...
	
	// zmieniam
	wsk ->_0 = 1; // pierwszy bit w pierwszym bajcie na "1"
	(wsk + 3) ->_1 = 1; // drugi bit w czwartym bajcie na "1"
	
	cout << liczba << endl; // co daje liczbę: 33554433
	
	return 0;
}

 

Wtedy dostajesz to co widoczne jest na screenie z kalkulatora (patrząc na bity od 0-31).

bity.thumb.jpg.a930944d907a4365168f0e8b3392138f.jpg

Edytowano przez orb777
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.