Strona 1 z 1
Programowe SPI proszę o sprawdzeni
: piątek 09 cze 2017, 20:30
autor: StaryAnoda
Hej
Możecie sprawdzić czy ta obsługa SPI zarówno odbiór jak i nadawanie jest poprawne ?
Czy dobrze rozumiem według tego rysunku dane są odbierane i wysyłane od najbardziej znaczącego do najmniej ?
Oraz czy odpowiednio próbkuję dane na odpowiednim zboczu.
Test.png
Kod: Zaznacz cały
uint8_t SPI_Read_and_Write(uint8_t byte)
{
uint8_t cnt = 0x80, Read_Byte = 0,i = 0;
DIGITAL_IO_SetOutputLow(&CSB);
DIGITAL_IO_SetOutputLow(&SCL);
while(cnt)
{
if(byte & cnt)
{
DIGITAL_IO_SetOutputHigh(&SDA);
}
else
{
DIGITAL_IO_SetOutputLow(&SDA);
}
DIGITAL_IO_SetOutputHigh(&SCL);
for(I = 100; I; I--)
{
}
DIGITAL_IO_SetOutputLow(&SCL);
cnt >>=1;
}
for (i = 0; i < 8; i++)
{
DIGITAL_IO_SetOutputHigh(&SCL);
if(DIGITAL_IO_GetInput(&SDO))
{
Read_Byte |= 0x01 << i;
}
DIGITAL_IO_SetOutputLow(&SCL);
}
DIGITAL_IO_SetOutputHigh(&CSB);
return Read_Byte;
}
Pytam ponieważ próbuję skomunikować się z czujnikiem ale z niewiadomych powodów nie mogę wolę sie upewnić.
Re: Programowe SPI proszę o sprawdzeni
: piątek 09 cze 2017, 21:01
autor: Antystatyczny
Potencjalny problem widzę tu:
Do zmiennej Read_Byte wpisujesz tak naprawdę 0x02, a pewnie wolałbyś wpisać 0x01, a następnie całość przesunąć w lewo o jedno miejsce. Proponuję taki kod:
Re: Programowe SPI proszę o sprawdzeni
: piątek 09 cze 2017, 21:13
autor: StaryAnoda
Ok dzięki dokonałem zmian:
Próbuję okiełznać ten czujnik:
https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdfMój kod wygląda następująco:
Kod: Zaznacz cały
while(1U)
{
Send_String("BMP280 ID NUMBER: ");
Send_Int(SPI_Read_And_Write(0xD0));
Send_String("\r\n");
for(I = 1000000; I; I--)
{
}
}
uint8_t SPI_Read_And_Write(uint8_t Byte)
{
uint8_t Cnt = 0x80, Read_Byte = 0, I = 0, A = 0;
DIGITAL_IO_SetOutputLow(&CSB);
DIGITAL_IO_SetOutputLow(&SCL);
while(Cnt)
{
if(Byte & Cnt)
{
DIGITAL_IO_SetOutputHigh(&SDA);
}
else
{
DIGITAL_IO_SetOutputLow(&SDA);
}
DIGITAL_IO_SetOutputHigh(&SCL);
for(I = 10; I; I--)
{
}
DIGITAL_IO_SetOutputLow(&SCL);
Cnt >>=1;
}
for (A = 0; A < 8; A++)
{
DIGITAL_IO_SetOutputHigh(&SCL);
for(I = 10; I; I--)
{
}
if(DIGITAL_IO_GetInput(&SDO))
{
Read_Byte |= 0x01;
Read_Byte <<= 1;
}
DIGITAL_IO_SetOutputLow(&SCL);
}
DIGITAL_IO_SetOutputHigh(&CSB);
return Read_Byte;
}Próbuję odczytać ID i otrzymuje 6.
Skąd mam wiedzieć jaki jest rzeczywiście adres tego układu.
0x60 to adres po resecie.
Re: Programowe SPI proszę o sprawdzeni
: piątek 09 cze 2017, 21:15
autor: Antystatyczny
Wygląda na to, że czytasz odwrotnie. 0x60 to 0b0110 0000, a Ty odczytujesz 0x06, czyli 0b0000 0110. Dokładna odwrotność...
Re: Programowe SPI proszę o sprawdzeni
: piątek 09 cze 2017, 22:04
autor: xor
Próbuję odczytać ID i otrzymuje 6.
Skąd mam wiedzieć jaki jest rzeczywiście adres tego układu.
0x60 to adres po resecie.
To nie jest adres tylko identyfikator układu, czy raczej typu czujnika. Jest zawsze ten sam.
Ja mam uwagę, która możliwe, ale niekoniecznie odnosi się do uzyskanego wyniku.
Zdaje się, że próbujesz zastosować tryb "11", ale nie jestem pewien, czy go faktycznie ustawiasz (uwielbiam analizować fragmenty programu wyrwane z całości

). Być może za pierwszym obrotem pętli jest to ustawione, ale za drugim i kolejnych wydaje mi się możliwym, że nie, albowiem po wyjściu z funkcji rspi_ead_and_write pozostawiasz SCL jako LOW, a jak mówi pismo święte na stronie 32: "The automatic selection between mode ‘00’ and ‘11’ is determined by the value of SCK after the CSB falling edge." a na łobrasku na następnej stronie wyraźnie widać, że SCL po opadającym zboczu CSB w tym trybie jest HIGH.
Re: Programowe SPI proszę o sprawdzeni
: piątek 09 cze 2017, 22:14
autor: Antystatyczny
Przeanalizowałem diagram czasowy i wydaje mi się, że taka forma będzie poprawna:
Kod: Zaznacz cały
uint8_t SPI_Read_And_Write(uint8_t Byte)
{
uint8_t Cnt = 0x80, Read_Byte = 0;
DIGITAL_IO_SetOutputLow(&CSB);
while(Cnt)
{
Read_Byte <<= 1;
DIGITAL_IO_SetOutputLow(&SCL);
if(Byte & Cnt)
{
DIGITAL_IO_SetOutputHigh(&SDA);
}
else
{
DIGITAL_IO_SetOutputLow(&SDA);
}
if(DIGITAL_IO_GetInput(&SDO))
{
Read_Byte |= 0x01;
}
DIGITAL_IO_SetOutputHigh(&SCL);//slave reads bit at rising edge
Cnt >>=1;
}
DIGITAL_IO_SetOutputHigh(&CSB);
return Read_Byte;
}
Re: Programowe SPI proszę o sprawdzeni
: sobota 10 cze 2017, 10:59
autor: StaryAnoda
Ok pytań ciąg dalszy:
Chcę używać trybu CPOL = CPHA = '1'
Zgodnie z tym rysunkiem:
Test.png
Według tego rysunku próbkowanie jest ustawione na zboczę opadające.
xor przed pętlą główną ustawiłem SCK na HIGH.
Mój kod wygląda następująco:
Kod: Zaznacz cały
/*
* main.c
*
* Created on: 2017 Jun 09 12:18:56
* Author: StaryKatoda
*/
#include <DAVE.h> //Declarations from DAVE Code Generation (includes SFR declaration)
#include <stdio.h>
/**
* @brief main() - Application entry point
*
* <b>Details of function</b><br>
* This routine is the application entry point. It is invoked by the device startup code. It is responsible for
* invoking the APP initialization dispatcher routine - DAVE_Init() and hosting the place-holder for user application
* code.
*/
uint32_t I;
void Send_Char(char B);
void Send_String(char * String);
void Send_Int(int Value);
uint8_t SPI_Read_And_Write(uint8_t Byte);
int main(void)
{
DAVE_STATUS_t status;
status = DAVE_Init(); /* Initialization of DAVE APPs */
DIGITAL_IO_SetOutputHigh(&SCL);
if(status != DAVE_STATUS_SUCCESS)
{
/* Placeholder for error handler code. The while loop below can be replaced with an user error handler. */
XMC_DEBUG("DAVE APPs initialization failed\n");
while(1U)
{
}
}
/* Placeholder for user application code. The while loop below can be replaced with user application code. */
while(1U)
{
Send_String("BMP280 ID NUMBER: ");
Send_Int(SPI_Read_And_Write(0xD0));
Send_String("\r\n");
Send_String("Temp_msb value: ");
Send_Int(SPI_Read_And_Write(0xFA));
Send_String("\r\n");
for(I = 1000000; I; I--)
{
}
DIGITAL_IO_SetOutputHigh(&LED_0);
DIGITAL_IO_SetOutputLow(&LED_1);
for(I = 1000000; I; I--)
{
}
DIGITAL_IO_SetOutputLow(&LED_0);
DIGITAL_IO_SetOutputHigh(&LED_1);
}
}
void Send_Char(char B)
{
UART_Transmit(&UART_0, &B, 1);
}
void Send_String(char * String)
{
while(*String)Send_Char(*String++);
}
void Send_Int(int Value)
{
char Bufor[50];
sprintf(Bufor, "%i", Value);
Send_String(Bufor);
}
uint8_t SPI_Read_And_Write(uint8_t Byte)
{
uint8_t Cnt = 0x80, Read_Byte = 0, I = 0, A = 0;
DIGITAL_IO_SetOutputLow(&CSB);
while(Cnt)
{
DIGITAL_IO_SetOutputHigh(&SCL);
if(Byte & Cnt)
{
DIGITAL_IO_SetOutputHigh(&SDA);
}
else
{
DIGITAL_IO_SetOutputLow(&SDA);
}
DIGITAL_IO_SetOutputLow(&SCL);
Cnt >>=1;
}
for (A = 0; A < 8; A++)
{
DIGITAL_IO_SetOutputHigh(&SCL);
if(DIGITAL_IO_GetInput(&SDO))
{
Read_Byte |= 0x01;
Read_Byte <<= 1;
}
DIGITAL_IO_SetOutputLow(&SCL);
}
DIGITAL_IO_SetOutputHigh(&SCL);
DIGITAL_IO_SetOutputHigh(&CSB);
return Read_Byte;
}
Analizator stanów logicznych ustawiłem w taki sposób:
Test2.png
I tutaj mam pytanie dlaczego program ustawia przy próbkowaniu zbocze narastające a nie opadające
(Jest tu jakaś nieścisłość chyba. W nocie CPOL = CPHA = '1' próbkuję na opadającym)
Test3.png
I tak widać, że Nadawanie jest chyba w porządku od strony mikrokontrolera, odbieranie zawodzi co widać tutaj:
Test4.png
Re: Programowe SPI proszę o sprawdzeni
: sobota 10 cze 2017, 11:08
autor: xor
Proponuję wywalić sterowanie CSB poza funkcję SPI_Read_and_Write co umożliwi transmisje blokowe a jest to w trybie NORMAL nie tylko porządane ale wręcz niezbędne. Zresztą w transmisji "pojedynczej" mieszanie CSB miedzy adresem a zapisem/odczytem danej może powodować błędy (chyba).
To uwagi do funkcji Antystatycznego, bo to co ty robisz z tą funkcją IMHO kwalifikuje się do lekkiego naprostowania (ale to później bo teraz muszę wyjść)
Re: Programowe SPI proszę o sprawdzeni
: sobota 10 cze 2017, 13:36
autor: StaryAnoda
Hejka
Xor nic to nie dało, dalej takie same objawy.
W sensie wyciągniecie pinu CSB poza funkcję.
Re: Programowe SPI proszę o sprawdzeni
: sobota 10 cze 2017, 17:58
autor: xor
I tutaj mam pytanie dlaczego program ustawia przy próbkowaniu zbocze narastające a nie opadające
(Jest tu jakaś nieścisłość chyba. W nocie CPOL = CPHA = '1' próbkuję na opadającym)
W tym trybie ustawianie jest na "leading edge", próbkowanie na "trailing edge", ale zauważ, że w trybie nieaktywnym zegar jest HIGH, a więc "leading edge" to zbocze opadające, a "trailing" to rosnące.
Uwaga na marginesie: W drugim trybie tego czujnika "00" ustawianie jest na "trailing" próbkowanie na "leading", zegar w stanie idle jest LOW, a więc próbkowanie też będzie na zboczu rosnącym.
Wracając do programu: Niepotrzebnie gmerasz a funkcji spi_read_write. Funkcja ma za zadanie wysłać i jednocześnie odczytać jeden bajt. Prosta funkcja z jasno zdefiniowanym, łatwym do zrozumienia działaniem. Koniec, kropka. Jej kod wygląda dobrze, nawet analiza gołym okiem, bez testowania wskazuje, że prawdopodobnie będzie działać bezbłędnie. Dodawanie do niej dalszych funkcji jest niecelowe, komplikuje ją, naraża na trudne do wyłapania błędy.
Dalszy kod można konstruować na bazie tej funkcji, a mógłby wyglądać tak:
Kod: Zaznacz cały
#define ID_REG 0xD0
int main()
{
uint8_t byte;
...
//ustawienie trybu "11" (automagicznie przez czujnik)
DIGITAL_IO_SetOutputHigh(&SCL);
//aktywacja magistrali
DIGITAL_IO_SetOutputLow(&CSB);
//transmisja adresu rejestru
(void)SPI_Read_And_Write(ID_REG);
//odczytanie id z czujnika
byte = SPI_Read_And_Write(0);
//funkcja SPI_Read_And_Write pozostawia SCL w stanie HIGH więc następny wiersz niepotrzebny
//DIGITAL_IO_SetOutputHigh(&SCL);
//dezaktywacja magistrali
DIGITAL_IO_SetOutputHigh(&CSB);
//dalej wyświetlenie wartości byte
...
}
uint8_t SPI_Read_And_Write(uint8_t Byte)
{
uint8_t Cnt = 0x80, Read_Byte = 0;
while(Cnt)
{
Read_Byte <<= 1;
DIGITAL_IO_SetOutputLow(&SCL);
if(Byte & Cnt)
{
DIGITAL_IO_SetOutputHigh(&SDA);
}
else
{
DIGITAL_IO_SetOutputLow(&SDA);
}
if(DIGITAL_IO_GetInput(&SDO))
{
Read_Byte |= 0x01;
}
DIGITAL_IO_SetOutputHigh(&SCL);//slave reads bit at rising edge
Cnt >>=1;
}
return Read_Byte;
}Pomijam tu konieczność ustawiania lub zerowania najstarszego bitu adresu rejestru, bo w tym przypadku, przypadkowo bit jest ustawiony jak należy.
Re: Programowe SPI proszę o sprawdzeni
: sobota 10 cze 2017, 21:14
autor: StaryAnoda
Ok
Dzięki za pomoc, odebrałem poprawny identyfikator urządzenia.
Re: Programowe SPI proszę o sprawdzeni
: niedziela 11 cze 2017, 17:04
autor: StaryAnoda
Dobra teraz chciałem się zapytać czy dobrze odbieram tą temperaturę:
Tutaj wykrywam podłączony czujnik:
Kod: Zaznacz cały
DIGITAL_IO_SetOutputHigh(&SCL);
DIGITAL_IO_SetOutputLow(&CSB);
SPI_Read_And_Write(0xD0);
if(SPI_Read_And_Write(0) == 0x60)
{
Send_String(" Znaleziono BME280!!! ");
}
else
{
Send_String(" Nie znaleziono BME280!!! ");
}
DIGITAL_IO_SetOutputHigh(&CSB);
Tutaj ustawiam w rejestrze ctrl_meas bity 7 i 5 (czyli oversampling *16) oraz bity 1 i 0 (czyli normal mode)
Kod: Zaznacz cały
DIGITAL_IO_SetOutputHigh(&SCL);
DIGITAL_IO_SetOutputLow(&CSB);
SPI_Read_And_Write(0b01110100); // 0xF4
SPI_Read_And_Write(0b10100011); // 0xA3
DIGITAL_IO_SetOutputHigh(&CSB);
Tutaj odbieram dane Compensation parameter storage:
Zgodnie z tabelą:
Tsessss.png
Kod: Zaznacz cały
uint16_t dig_t1;
int16_t dig_t2;
int16_t dig_t3;
DIGITAL_IO_SetOutputHigh(&SCL);
DIGITAL_IO_SetOutputLow(&CSB);
SPI_Read_And_Write(0b10001001);
dig_t1 = SPI_Read_And_Write(0);
dig_t1 = dig_t1 << 8;
DIGITAL_IO_SetOutputHigh(&CSB);
DIGITAL_IO_SetOutputHigh(&SCL);
DIGITAL_IO_SetOutputLow(&CSB);
SPI_Read_And_Write(0b10001000);
dig_t1 = dig_t1 |SPI_Read_And_Write(0);
DIGITAL_IO_SetOutputHigh(&CSB);
//
DIGITAL_IO_SetOutputHigh(&SCL);
DIGITAL_IO_SetOutputLow(&CSB);
SPI_Read_And_Write(0b10001011);
dig_t2 = SPI_Read_And_Write(0 );
dig_t2 = dig_t2 << 8;
DIGITAL_IO_SetOutputHigh(&CSB);
DIGITAL_IO_SetOutputHigh(&SCL);
DIGITAL_IO_SetOutputLow(&CSB);
SPI_Read_And_Write(0b10001010);
dig_t2 = dig_t2 |SPI_Read_And_Write(0);
DIGITAL_IO_SetOutputHigh(&CSB);
//
DIGITAL_IO_SetOutputHigh(&SCL);
DIGITAL_IO_SetOutputLow(&CSB);
SPI_Read_And_Write(0b10001101);
dig_t3 = SPI_Read_And_Write(0 );
dig_t3 = dig_t3 << 8;
DIGITAL_IO_SetOutputHigh(&CSB);
DIGITAL_IO_SetOutputHigh(&SCL);
DIGITAL_IO_SetOutputLow(&CSB);
SPI_Read_And_Write(0b10001100);
dig_t3 = dig_t3 |SPI_Read_And_Write(0);
DIGITAL_IO_SetOutputHigh(&CSB);
Tutaj odbieram 3 bajty zawierające temperaturę :
memory.png
Kod: Zaznacz cały
uint8_t MSB, LSB,XLSB;
// Read MSB
DIGITAL_IO_SetOutputHigh(&SCL);
DIGITAL_IO_SetOutputLow(&CSB);
SPI_Read_And_Write(0xFA);
for(I = 1000; I; I--)
{
}
MSB = SPI_Read_And_Write(0);
DIGITAL_IO_SetOutputHigh(&CSB);
// Read LSB
DIGITAL_IO_SetOutputHigh(&SCL);
DIGITAL_IO_SetOutputLow(&CSB);
SPI_Read_And_Write(0xFB);
for(I = 1000; I; I--)
{
}
LSB = SPI_Read_And_Write(0);
DIGITAL_IO_SetOutputHigh(&CSB);
// Read XLSB
DIGITAL_IO_SetOutputHigh(&SCL);
DIGITAL_IO_SetOutputLow(&CSB);
SPI_Read_And_Write(0xFC);
for(I = 1000; I; I--)
{
}
XLSB = SPI_Read_And_Write(0);
DIGITAL_IO_SetOutputHigh(&CSB);
Tutaj mam pytanie odnośnie konwersji tych trzech bajtów do jednej zmiennej
Kod: Zaznacz cały
int32_t Temp;
Temp = (int32_t)( ( ( (int32_t) MSB <<16 ) | ( (int32_t)LSB <<8 ) | ((int32_t) XLSB ) ) >> 4 );
Czy to przesunięci w prawo o 4 jest potrzebne czy nie ?
Tutaj funkcja zaczerpnięta z noty katalogowej:
ffffffffffffffffffff.png
Kod: Zaznacz cały
int32_t t_fine;
int32_t bmp280_compensate_T_int32(int32_t adc_T)
{
int32_t var1, var2, T;
var1 = ((((adc_T>>3) - ((int32_t)dig_t1 <<1))) * ((int32_t)dig_t2)) >> 11;
var2 = (((((adc_T>>4) - ((int32_t)dig_t1)) *
((adc_T>>4) - ((int32_t)dig_t1))) >> 12) *
((int32_t)dig_t3)) >> 14;
t_fine = var1 + var2;
T = (t_fine * 5 + 128) >> 8;
return T;
}
Tutaj wynik całego programu:
Czy macie jakieś uwagi ?
Czy dobrze interpretuję że temperatura wynosi 25.26 St C.
Terminal.png
Re: Programowe SPI proszę o sprawdzeni
: niedziela 11 cze 2017, 18:39
autor: xor
Mam cztery uwagi:
1. Te bloki powinny być zamknięte w funkcjach (nie wiem, może są ale tego nie widać w listingach)
2. Nie stosuj tzw. magic numbers. Zamiast
Kod: Zaznacz cały
SPI_Read_And_Write(0b01110100); // 0xF4
SPI_Read_And_Write(0b10100011); // 0xA3wpisz
Kod: Zaznacz cały
//gdzieś w pliku .h albo w .c w bloku różnych definicji
#define CTRL_MEAS_REG 0xF4
#define TEMP_OVS_16 ((0b101)<<5)
#define NORMAL_MODE (0b11)
//.....
SPI_Read_And_Write(CTRL_MEAS_REG);
SPI_Read_And_Write(TEMP_OVS_16 + NORMAL_MODE);Oczywiście przy SPI trzeba pamiętać o bicie R/W (Ty to zrobiłeś ręczno nożnie), proponuję utworzyć odpowiednią funkcję (albo makro) żeby nie zaprzątać sobie głowy czy wyzerować czy ustawić bit. Wtedy pierwsze wywołanie SPI_Read_And_Write może wyglądać np. tak:
Kod: Zaznacz cały
SPI_Read_And_Write(spi_write(CTRL_MEAS_REG));a funkcje np. tak
Kod: Zaznacz cały
uint8_t spi_write(uint8_t address)
{
return address & 0x7f;
}
uint8_t spi_read(uint8_t address)
{
return address | 0x80;
}3. Źle odczytujesz rejestry danych. W trybie NORMAL trzeba je odczytywać jako blok, nie po jednym. Odczytywanie po jednym rejestrze może prowadzić do błędów, jeżeli konwersja zakończy się pomiędzy odczytami (a w trybie NORMAL konwersja wykonuje się automatycznie co ustalony czas). Wtedy z części rejestrów ma się dane z poprzedniej konwersji a z części z bieżącej. Przy odczycie blokowym jest zagwarantowana spójność danych. Jest to opisane w datasheecie.
Dane korekcyjne też odczytujesz po jednym, to nie jest błąd bo dane są niezmienne, ale to niepotrzebnie spowalnia i komplikuje program -> też można odczytać blokiem.
A więc potrzebujesz funkcji blokowego odczytu danych (blokowy zapis też mógłby się przydać, ale to nie jest krytyczne) np. takiej:
Kod: Zaznacz cały
#define DUMMY 0
void spi_read_block(uint8_t *buffer, uint8_t address, uint8_t len)
{
DIGITAL_IO_SetOutputHigh(&SCL);
DIGITAL_IO_SetOutputLow(&CSB);
SPI_Read_And_Write(spi_read(address));
while(len--)
*buffer++ = SPI_Read_And_Write(DUMMY);
DIGITAL_IO_SetOutputHigh(&CSB);
}wywołanie
Kod: Zaznacz cały
#define TEMP_REG 0xFA
#define TEMP_DATA_LEN 3
uint8_t buffer[TEMP_DATA_LEN]; //po wyjściu z funkcji zawiera kolejno temp_msb, temp_lsb, temp_xlsb
spi_read_block(buffer, TEMP_REG, TEMP_DATA_LEN); //odczyt nieskompensowanej temperaturyCo do prawidłowości wyliczeń się nie wypowiadam, bo po to bym nie musiał sobie tym zaprzątać głowy producent czujnika przygotował odpowiedni driver

Re: Programowe SPI proszę o sprawdzeni
: niedziela 11 cze 2017, 22:34
autor: StaryAnoda
Wielkie dzięki kolego
Jutro naniosę poprawki.
Re: Programowe SPI proszę o sprawdzeni
: poniedziałek 12 cze 2017, 08:21
autor: xor
Tutaj mam pytanie odnośnie konwersji tych trzech bajtów do jednej zmiennej
Kod: Zaznacz cały
int32_t Temp;
Temp = (int32_t)( ( ( (int32_t) MSB <<16 ) | ( (int32_t)LSB <<8 ) | ((int32_t) XLSB ) ) >> 4 );Czy to przesunięci w prawo o 4 jest potrzebne czy nie ?
Tak, jest potrzebne albowiem w XLSB wartość jest przechowywana w 4 starszych bitach, na 4 młodszych bitach jest zawsze zero.
Coś mi jednak nie pasowało w powyższym zapisie więc zajrzałem do źródeł drivera i tam przesunięcia są trochę inne:
MSB<<12
LSB<<4
XLSB>>4
W sumie daje to liczbę 20bitową, tak jak piszą przy okazji funkcji kompensującej temperaturę.
Re: Programowe SPI proszę o sprawdzeni
: poniedziałek 12 cze 2017, 09:04
autor: xor
No to jeszcze:
Obrazek z rozmieszczeniem rejestrów jest (chyba) od czujnika BMP, wydawało mi się, że mówimy o BME, jak to w końcu jest?
Diabelnie źle czyta się kod wczytujący dane kalibracyjne. Trudno dojrzeć czy nie ma tam buga. Proponuję to uczytelnić - najpierw odczyt blokowy, potem przepisanie do globalnej struktury (albo do niezależnych zmiennych ale wtedy funkcja musiała by odwoływać się do nich nie przez parametr lecz "bezpośrednio" - tego unikamy jak ognia). Całość w odrębnej funkcji.
Kod: Zaznacz cały
struct coefficients {
uint_16_t dig_T1;
int16_t dig_T2;
int16_t dig_T3;
/dalej współczynniki dla ciśnienia i wilgotnośći
...
} coeff;
...
void read_calib_data( struct coefficients *coef)
{
uint8_t buffer[CALIB_DATA_LEN];
spi_read_block(buffer, CALIB_REG, CALIB_DATA_LEN);
coef->dig_T1 = buffer[0] | buffer[1]<<8;
// ... itd ...
}
Re: Programowe SPI proszę o sprawdzeni
: poniedziałek 12 cze 2017, 09:13
autor: Antystatyczny
Jakie są przesłanki ku temu, by unikać jak ognia wczytywania pojedynczych zmiennych? Całość i tak jest zawarta w osobnym module, a zmienne można schować korzystając ze "static". Zmienne będą o zasięgu modułu, a funkcja/funkcje korzystające z tych danych będą miały bezpośredni dostęp. Oczywiście rozumiem, że chodzi tu o dane kalibracyjne, które odczytuje się tylko raz.
Re: Programowe SPI proszę o sprawdzeni
: poniedziałek 12 cze 2017, 09:18
autor: xor
Nie ma podstaw do założenia że jest to w odrębnym module. Na razie wygląda to na jeden wielki main.
W przypadku modułu oczywiście jest tak jak mówisz.
Zresztą, nawet w module lepiej to wygląda jak jest przekazywane przez parametr. I
MHO.
...ale generalnie zgadzam się z tym co jest napisane w następnych dwóch postach, 0144% zgody

Re: Programowe SPI proszę o sprawdzeni
: poniedziałek 12 cze 2017, 09:21
autor: Antystatyczny
Sądzę, że wszystko jest w main jedynie na czas testów, a potem tradycyjnie trafi do osobnego modułu. Prawdę mówiąc nawet nie spojrzałem na nazwę pliku, bo skupiłem się na samych funkcjach. Oczywiście masz rację, że w obecnej formie lepiej by to wyglądało w strukturze.
Re: Programowe SPI proszę o sprawdzeni
: poniedziałek 12 cze 2017, 09:32
autor: Antystatyczny
Przekazywanie wskaźnika na strukturę z danymi kalibracyjnymi do funkcji, gdy te dane są jedynymi i nigdy nie ulegają podmianie, jest w mojej ocenie zbędnym obciążaniem rejestrów/stosu. Jak już wspomniałem wcześniej, zmienne są ukryte przed światem zewnętrznym i nie ma powodu, by dodatkowo tworzyć wskaźnik na strukturę w wywołaniu funkcji wykorzystującej dane kalibracyjne. Oczywiście dane mogą być w strukturze, to ładnie wygląda i poprawia czytelność, ale do pól można się odwoływać bezpośrednio.
Re: Programowe SPI proszę o sprawdzeni
: poniedziałek 12 cze 2017, 22:04
autor: StaryAnoda
Ok dzięki za pomoc koledzy

Musi mi się to wszystko przetrawić

Na razie zajmuję się uporządkowaniem biblioteki, podziałem na poszczególne moduły. Za niedługo uruchomię pomiar ciśnienia i wilgotności.
Xor masz rację zrzut ekranu jest z innego czujnika nie wiem jakim prawem miałem go otwartego w przeglądarce. Cały czas mówimy o BME280.