PIC, SPI komunikace, Generátor funkcí

arduino, teensy, atmega, pic a jine (software, hardware)
Odpovědět
Onder
Příspěvky: 134
Registrován: 6. 4. 2021, 2:14

27. 1. 2025, 9:19

Ahoj,

experimentuju a nedaří se mi dohledat na internetu kde mám chyby, tak to mezitím zkusím tady, vím že se tu někteří vyznají.

Chci postavit generátor funkcí s AD9833, mám PIC16F877a a momentálně vůbec bojuji s nastavením SPI komunikace. Princip jsem okoukal: https://deepbluembedded.com/spi-tutoria ... ntrollers/, k ovládání AD9833 potřebuji jen přes SPI posílat data tedy SDO.

K věci - mám primitivní funkci pro zápis hodnot:
  • void SPI_Write_8(uint8_t Data)
    {
    //while (SSPSTATbits.BF == 1); //pokud je plny registr tak se ceka
    SSPBUF = Data;
    }
tedy když funkci zavolám přes tlačítko:
  • if(RB4)
    {
    PORTBbits.RB1 = 0;
    __delay_ms(200);
    SPI_Write_8(10);
    }
tak bych očekával že uvidím odpovídající sekvenci bitů - pozoruji to logickým analizátorem: https://dratek.cz/arduino/2187-logicky- ... odbus.html

akorát ty hodnoty co pozoruji tak se úplně neslučují s tím co tam má být a ještě k tomu se ty hodnoty mění - tedy nevidím pořad stejné číslo, ale většinou se to náhodně střídá mezi 1 a 128 (decimálně).
Snímek obrazovky 2025-01-27 102434.png
Taky nechápu proč tam vždy je něco na tom channel 2, sice je připojený na SDI, ale s tím se nic nedělá.

K SCL a SDO na PICu mám připojený pouze ten logický analizátor, na ty piny není nic jiného připojené. - Nenašel jsem že by tam bylo potřeba třeba nějakého rezistoru připojeného.

Co si myslím že mám správně: správně inicializovaný SPI a příslušně nastavené SPI v software pro logický analizátor (idle stav clk a hranu)

Nenapadá někoho kde by mohl být problém?
Onder
Příspěvky: 134
Registrován: 6. 4. 2021, 2:14

27. 1. 2025, 10:57

Tak jsem přidal nějaké delay(e) a z 95% to vypadá že to funguje, nevím jestli to je správný přístup ale co už, stejně vím že mi tam toho nebude fungovat více :lol:
miv
Příspěvky: 1162
Registrován: 17. 9. 2019, 11:55

27. 1. 2025, 10:51

Onder píše: 27. 1. 2025, 10:57 Tak jsem přidal nějaké delay(e) a z 95% to vypadá že to funguje, nevím jestli to je správný přístup ale co už, stejně vím že mi tam toho nebude fungovat více :lol:
Úplně ti tam chybí čekání na dokončené vyslání. Prostě jsi tam nacpal data a předpokládáš, že je SPI připraven. To ovšem nemusí být pravda. Těmi delay jsi to zpomalil, takže to začalo nějak chodit. Prostuduj si pořádně ty funkce SPIWrite a spol. Máš k té knihovně určitě i zdrojáky, tam to uvidíš. A doporučuji i dokumentaci k CPU. Pak to vše budeš chápat lépe.
Onder
Příspěvky: 134
Registrován: 6. 4. 2021, 2:14

28. 1. 2025, 11:19

miv píše: 27. 1. 2025, 10:51 Úplně ti tam chybí čekání na dokončené vyslání. Prostě jsi tam nacpal data a předpokládáš, že je SPI připraven. To ovšem nemusí být pravda. Těmi delay jsi to zpomalil, takže to začalo nějak chodit. Prostuduj si pořádně ty funkce SPIWrite a spol. Máš k té knihovně určitě i zdrojáky, tam to uvidíš. A doporučuji i dokumentaci k CPU. Pak to vše budeš chápat lépe.
Z knihoven to není, ani jsem se doteď na žádnou nedíval, jel jsem podle toho článku (viz. první příspěvek). Ale teď jsem se podíval na něčí implementaci SPI zápisu :

Kód: Vybrat vše

unsigned char writeSPIByte(unsigned char data)
{
  SSPSTATbits.BF = 0;
  unsigned char i;
  SSPBUF = data;
  while(SSPSTATbits.BF == 0){}
  return SSPBUF;
} 
a jediné co má naopak, tak je to čtení příznaku BF z registru SSPSTAT, což je dle datasheetu (se kterým(i) se snažím pracovat ale častokrát z toho nejsem moc moudrý):

BF: Buffer Full Status bit (Receive mode only)
1 = Receive complete, SSPBUF is full
0 = Receive not complete, SSPBUF is empty

, aktuálně to teda mám takto pro zápis:

Kód: Vybrat vše

void SPI_Write_8(uint8_t Data)
{
    
    SSPBUF = Data;
    while (SSPSTATbits.BF == 0); 
}

void SPI_Write_16(uint16_t Data)
{
    
    SSPBUF = (Data >> 8);
    while (SSPSTATbits.BF == 0); 
    //__delay_us(2);
    
    
    SSPBUF = (Data & 0xFF);
    while (SSPSTATbits.BF == 0); 
    //__delay_us(10);
    
    
    //SPI_Write_8(Data >> 8);
    //SPI_Write_8(Data & 0xFF);
}
a vypadá že to "funguje" - myšleno že jsem z mého malého testování nezpozoroval zaslání chybných bitů. Takže SPI teď asi chvíli nechám a jdu rozlouskat jak přepsat něčí knihovnu pro AD9833 pro arduino, které je v c++. Je to zapsané v třídách a musím to nějak rozluštit jak se s tím pracuje abych to byl schopen zapsat do C.

Btw. AD9833 potřebuje pro ovládání příjem 16ti bitů a PICem pošlu max 8, proto tam je ta funkce na zaslání 16ti - takže 2x volám zápis 8mi bitů.

Když odstraním ty delaye (jsou zakomentované v SPI_write_16) tak mám dvě možnosti jak poslat 2x 8 bitů.

1. 2x zavolat funkci pro zápis 8 bitů, výsledek:
Snímek obrazovky 2025-01-28 115405.png
2. 2x použít nahrání dat do SSPBUF a čekat, výsledek:
Snímek obrazovky 2025-01-28 121115.png
tento způsob má menší prodlevu

když jsem tam ty smyčky while neměl musel jsem tam dát delaye a byl jsem schopen ty prodlevy mezi 8 bity ještě více zkrátit (už si to nepamatuju kolik to bylo ale kolem 3us)

Ty smyčky while jsem odstranil (zakomentoval), protože když tam byly tak se mi to na nich zaseklo - asi protože nic krom logického analyzátoru nebylo připojeno na piny SDO a SDI. Teď jsem to udělal tak, že jsem ty piny navzájem spojil 1k odporem, takže to samé co se vyšle se i přijme.

No proč to píšu - protože jsem zvědavej, až (pokud) se mi podaří přepsat funkce pro ovládání AD9833, zda tyto prodlevy mezi každými 8mi bity nebudou vadit. Pokud si dobře vzpomínám, tak je potřeba zaslat i 16+.... (32?) bitů do registrů pro nastavení fáze/frekvence .
miv
Příspěvky: 1162
Registrován: 17. 9. 2019, 11:55

28. 1. 2025, 1:47

Onder píše: 28. 1. 2025, 11:19
No proč to píšu - protože jsem zvědavej, až (pokud) se mi podaří přepsat funkce pro ovládání AD9833, zda tyto prodlevy mezi každými 8mi bity nebudou vadit. Pokud si dobře vzpomínám, tak je potřeba zaslat i 16+.... (32?) bitů do registrů pro nastavení fáze/frekvence .
A to nemá ten SPI systém možnost být nastaven na 16 bitů? To je docela divné. Ještě bych podrobně prostudoval manuál.
Uživatelský avatar
Radhard
Příspěvky: 306
Registrován: 1. 7. 2020, 10:19
Bydliště: Praha
Kontaktovat uživatele:

28. 1. 2025, 8:44

miv píše: 28. 1. 2025, 1:47 A to nemá ten SPI systém možnost být nastaven na 16 bitů? To je docela divné. Ještě bych podrobně prostudoval manuál.
To 8bity často nemají. Některé ARM už ano (i nebinární počty bitů).

A ono to něčemu vadí ?
miv
Příspěvky: 1162
Registrován: 17. 9. 2019, 11:55

28. 1. 2025, 9:33

Radhard píše: 28. 1. 2025, 8:44
miv píše: 28. 1. 2025, 1:47 A to nemá ten SPI systém možnost být nastaven na 16 bitů? To je docela divné. Ještě bych podrobně prostudoval manuál.
To 8bity často nemají. Některé ARM už ano (i nebinární počty bitů).

A ono to něčemu vadí ?
Nevím, zda to vadí - to by řekl manuál k ovládanému obvodu, zda má nějaké omezení. V každém případě je to však pak jednodušší na ovládání.
Uživatelský avatar
Radhard
Příspěvky: 306
Registrován: 1. 7. 2020, 10:19
Bydliště: Praha
Kontaktovat uživatele:

29. 1. 2025, 10:57

Zběžně jsem se kouknul, tak timeout nemá. Protokol je celkem trivka. Jedna 16 bit transakce kde je zakódovaný všechno co potřebuješ nastavit. Vzhledem k tomu jak to mají pomíchaný, tak je úplně jedno jestli to poskládá z 1x16 nebo 2x8.
Onder
Příspěvky: 134
Registrován: 6. 4. 2021, 2:14

30. 1. 2025, 9:54

Vzhledem k tomu že nastala ta situace, kdy jsem věděl na 99% že mi to nebude hned fungovat, jak přepíšu ovládání AD9833, tak se nyní učím jak v MPLAB X IDE debuggovat, co mě překvapilo tak to asi vypadá, že jsem schopen pomocí programátoru pickit ovládat provádění instrukce za instrukcí, když si klikám v mplabu x ide a mohu pozorovat kde se co mění, aktuální hodnoty proměnných a jak to skáče.

Co je spíš nemilé tak to, že opětovně se po SPI posílají občas nějaké jiné data (většinou když pozoruji 8 bitů, tak se to většinou střídá na stále stejných pozicích.

Co mě napadá za příčinu tak to může být 1. špatný kód v logice / SPI nastavení (pravděpodobné - ale když jsem se díval na cizí SPI ovládání tak to mají dle mě stejně), 2. logický analyzátor si ze mě dělá srandu

Ještě to teoreticky mohu pozorovat osciloskopem, ale jednou se mi stalo, že když jsem něco pozoroval na arduinu, tak jsem ho tím zabil. Někde to zkratlo. Včera jsem zkoušel pozorovat výstup z AD9833 a kupodivu to nějakou škaredou sinusovku produkovalo z prvotního init nastavení (chtěl jsem přes tlačítka měnit frekvenci ale přes SPI to posílalo špatně - teď tedy debuggingem se chci podívat zda je příčina ve špatné logice kódu a posílají se správně vypočtené data, nebo ne), ale napájení jsem měl přes lab. zdroj. Ve spěchu jsem taky omylem na chvíli měl napájení z PC přes programátor a taky jsem to pozoroval osciloskopem a asi se nic tentokrát nestalo, ale i tak to radši takto nebudu dělat.
Onder
Příspěvky: 134
Registrován: 6. 4. 2021, 2:14

30. 1. 2025, 3:05

Tak z pozorování hodnot, které se mají přes SPI poslat jsem zpozoroval, že poslané data se neshodují s těmi které se měly poslat (většinou se pošlou správné, občas se pošlou špatné :? ), takže chyba v logice není a chyba je v SPI :roll: Mě z toho picu picne
miv
Příspěvky: 1162
Registrován: 17. 9. 2019, 11:55

30. 1. 2025, 4:31

Onder píše: 30. 1. 2025, 3:05 Tak z pozorování hodnot, které se mají přes SPI poslat jsem zpozoroval, že poslané data se neshodují s těmi které se měly poslat (většinou se pošlou správné, občas se pošlou špatné :? ), takže chyba v logice není a chyba je v SPI :roll: Mě z toho picu picne
Jsi si jist, že to SPI používá jen ten tvůj kód? SPI signály SIMO, SOMI bývají společné a výběr obvodu se řeší CS signálem. Musíš tedy ještě generovat chip select signál. To mimochodem budeš muset řešit při skutečném ovládání toho obvodu, protože velmi pravděpodobně ta 16-ti bitová transakce musí proběhnout pod jedním cyklem chip select signálu.
Onder
Příspěvky: 134
Registrován: 6. 4. 2021, 2:14

1. 2. 2025, 10:09

miv píše: 30. 1. 2025, 4:31
Jsi si jist, že to SPI používá jen ten tvůj kód? SPI signály SIMO, SOMI bývají společné a výběr obvodu se řeší CS signálem. Musíš tedy ještě generovat chip select signál. To mimochodem budeš muset řešit při skutečném ovládání toho obvodu, protože velmi pravděpodobně ta 16-ti bitová transakce musí proběhnout pod jedním cyklem chip select signálu.
Ano slave select mám v kódu implementovaný a i na ad9833 připojený, mám to jen tak, že předtím, než se odešlou data přes SPI, tak se SS pin stáhne na low a po provedení SPI přejde pin na high.

Nechám to SPI teďka tak, protože já s tím nemám zkušenosti a podle mě těch důvodů proč to nejede může být mraky. Takže teďka se pokusím implementovat kód pro posílání přes I2C a připojím si displej a pokusím se zobrazovat si posílané hodnoty. I2C používá stejný vnitřní modul v PICu jako SPI, takže to budu muset nějak míchat (ale asi jen bude vždy potřeba přepínat mezi nastaveními modulu v závislosti na tom, přes co zrovna chci posílat). Ten modul má 2 registry které se musí natavit. To I2C jsem už jednou zkoušel a jestli si dobře vzpomínám tak s tím nebyly takové problémy a posílalo to správně a ne nějaké PIC*viny.
miv
Příspěvky: 1162
Registrován: 17. 9. 2019, 11:55

1. 2. 2025, 12:27

Onder píše: 1. 2. 2025, 10:09 To I2C jsem už jednou zkoušel a jestli si dobře vzpomínám tak s tím nebyly takové problémy a posílalo to správně a ne nějaké PIC*viny.
SPI funguje výborně. Doporučil bych chybu hledat mezi židlí a klávesnicí. Je to nejčastější případ. :)
atlan
Příspěvky: 3382
Registrován: 7. 2. 2011, 9:12

1. 2. 2025, 3:45

Ak mas vela casu, ukaz kod pre cast SPI.... chat GPT
Odpovědět

Zpět na „MCU“