AM/FM predajnik za testiranje starih radio prijemnika (drugi dio)


 

 

… Nastavak objave AM/FM predajnik za testiranje starih radio prijemnika

 

 

Kroz objavu AM/FM predajnik za testiranje starih radio prijemnika opisao sam postupak odabira dijelova i komponenti za gradnju testnog AM/FM radio predajnika širokog raspona frekvencija (100 KHz – 160 MHz). On bi se mogao koristiti kao izvor testne RF emisije za razne stare radio prijemnike koji rade na različitim frekvencijama i različitim modulacijama, na kojima danas više nema nikakvih komercijalnih emisija.

Predajnik mora biti što jednostavniji i što jeftiniji za gradnju jer je plan napraviti set od 5 ili 10 takvih predajnika za istovremeno emitiranje na više frekvencija/modulacija. Stoga je cilj naći dostupna rješenja sa najboljim omjerom cijene i dobivenih performansi.

 

Sažetak

Za osnovni oscilator (VFO), nakon pregleda više različitih specijaliziranih čipova za tu namjenu,  odabrao sam popularnu konstrukciju VFO-a sa modulom Si5351 koja je proizašla od japanskog radio amatera JF3HZB i kasnije modificirani od više drugih elektroničara i radioamatera. Postoje VFO čipovi sa puno boljim karakteristikama, no oni su i puno skuplji i teži za nabavu.

Za amplitudni modulator sam odabrao također vrlo jeftin čip MC1496 koji se pokazao daleko boljim od bilo kojeg jednostavnog tranzistorskog modulatora koji sam testirao.

Što se tiče FM modulatora, on mora raditi na takt frekvenciji čipa za VFO Si5351, koja mora biti u rasponu 25-27 MHz. S obzirom da FM modulator zapravo mijenja kristal VFO čipa, u obzir dolaze samo modulatori kojima je baza kristalni oscilator. Testirao sam nekoliko kristalnih oscilatora sa tranzistorima i logičkim inverterima. Oscilator sa inverterima se pokazao kao dobar temelj za FM modulator, međutim, tražim neko bolje rješenje.

Frekvencije 25-27 MHz su inače vrlo slabo zastupljene glede gotovih rješenja VCO-a (što čudi jer je to dijelom CB opseg). Čipovi za te frekvencije (PLL+VCO) su danas teško nabavljivi, a adekvatni VCO moduli prilično skupi. S druge strane, tržište je preplavljeno različitim jeftinim FM predajnicima za komercijalni UKV FM opseg. Neki od njih se baziraju na namjenskim digitalnim čipovima koji osiguravaju dobru stabilnost frekvencije i dobru FM modulaciju. Problem je što većina tih čipova ne radi ispod 70 MHz.

Međutim, posve slučajno, uspio sam otkriti jedan kineski čip koji je deklariran za najnižu frekvenciju od 27 MHz. Isti ima oznaku HS6760. Napravio sam opsežne testove toga čipa i pokazao se kao vrlo dobar kandidat za FM modulaciju. Čip je tvornički programiran na osam frekvencija u rasponu 40-88,7 MHz i potrebno ga je pre-programirati na 27 MHz.

S obzirom da nisam stručnjak za programiranje, evo kako je tekao moj pokušaj  pre-programiranja čipa HS6760.

 


 

 Programiranje čipa HS6760

Čip HS6760 se od početne inačice v1.0 s kraja 2015. godine postepeno razvijao tako da prema podacima koje sam uspio naći posljednja šesta inačica ovog čipa ima oznaku v2.4 i datira iz srpnja 2016. godine. Uspio sam iskopati neki osnovni kineski datasheet za inačice v1.3 i v2.0 iz kojih se mogu iščitati tek opće značajke i način programiranja čipa preko I2C sabirnice. Ne znam koja inačica čipa je na našem modulu, pretpostavljam posljednja. Nažalost, uz sav moj trud nisam mogao skinuti dokumentaciju za inačicu v2.4 jer se traži neka specifična kineska registracija na službenim stranicama koja ne podržava ni strane jezike (samo kineski) ni registraciju iz većine stranih država, uključujući i Hrvatsku. Kako god bilo, svakako ću probati preprogramirati ovaj čip za potrebe projekta (frekvencija 27 MHz, devijacija 22,5 kHz), iako očekujem puno problema oko toga.

Već smo rekli da se programiranje čipa HS6760 vrši preko široko korištene standardne serijske I2C sabirnice za koju su dovoljne dvije žice: SCK (takt signal) i SDA (dvosmjerna razmjena podataka). Da bi se čip prebacio u mod programiranja, pin 3-SEL se mora sa visoke logičke razine (Vcc) prebaciti na nisku logičku razinu (masa). Tada pinovi SCK i SDA više se služe za setiranje mono/stereo načina i odabir kanalne frekvencije, nego za I2C komunikaciju.

 

 

I2C (Inter-Integrated Circuit)

I2C (Inter-Integrated Circuit) standard omogućuje komunikaciju između velikog broja digitalnih uređaja gdje su svi paralelno povezani preko samo dvije fizičke žice. Pošto je ovo serijska komunikacija onda je u jednom trenutku moguća razmjena podataka između samo između dva uređaja, a selektiranje željenog uređaja se vrši preko njegove jedinstvene programske adrese.

Ovo možemo usporediti sa radio mrežom koja radi na principu selektivnog poziva (tonskog squelcha). Glavna upravljačka (master) radio postaja sa svakim pozivom šalje i identifikacijski broj korisničke (slave) postaje, tako da će se jedino kod postaje sa tim brojem otvoriti prijemnik i ostvariti komunikacija, bez obzira što su i sve druge postaje na istoj frekvenciji.

O I2C komunikaciji postoji puno internetskih tutorijala tako da ovdje nećemo objašnjavati sve detalje i specifičnosti ovog protokola, želim samo opisati one segmente koji su nužni za komunikaciju sa čipom HS6760.

Glavni uređaj u I2C komunikaciji koji istom upravlja u svim segmentima naziva se MASTER. Mi ćemo kao MASTER uređaj koristiti Arduino Mega 2560 mikrokontrolersku razvojnu ploču. SLAVE uređaj je naravno čip HS6760. On izvršava naredbe koje mu daje MASTER uređaj i šalje potvrdu da li su iste izvršene. Prvo moramo vidjeti koji je točan protokol slanja (zapisa) podataka na naš SLAVE čip, a to možemo vidjeti samo sa tvorničke dokumentacije čipa.

 

 

Ovo je u osnovi standardni protokol kod I2C komunikacije. Generalno gledano, prvo se šalje 7-bitna identifikacijska adresa uređaja (čipa), a onda se razmjenjuju 8-bitni paketi podataka u određene registre čipa. Nakon svake identifikacije i svakog razmijenjenog paketa, mora se dobiti potvrdni bit da je paket uredno upisan ili pročitan. Potvrdni bit je označen slovom A (acknowledge), a ukoliko nema potvrde (neuspješna prijava na adresu ili neuspješna razmjena podataka) takav bit je označen sa NA ili NACK (not-acknowledge).

Na početku u modu čekanja obje se linije (SLC i SDA) nalaze na logičkoj jedinici. Početak (START) i kraj (STOP) komunikacije određen je promjenom logičkog stanja SDA linije prema CLK liniji.

  • START – MASTER inicira početak komunikacije prebacivanjem SDA linije na logičku nulu u trenutku kada je SCL na logičkoj jedinici.
  • I2C CHIP ADDRESS (bitovi 1-7) – MASTER šalje 7-bitnu adresu uređaja sa kojim želi komunicirati. Adresa našeg čipa je
  • W (bit 8) – MASTER šalje bit koji govori da li će se podaci pisati na SLAVE uređaj (W) ili čitati sa SLAVE uređaja (R).
  • A (bit 9) – SLAVE uređaj šalje potvrdu (A – acknowledge) da je uspješno primio zahtjev za upis ili čitanje podataka postavljanjem SDA linije na logičku nulu. Ukoliko te potvrde nema (NA – not acknowledge) onda MASTER generira STOP bit i prekida komunikaciju.
  • REGISTER ADDRESS (bit 1-8) – MASTER šalje 8-bitnu adresu modula unutar čipa sa kojim želi komunicirati.
  • A (bit 9) – SLAVE uređaj šalje potvrdu zahtjeva za pristup registru (A – acknowledge).
  • REGISTER BIT <7:0> (bit 1-8) – MASTER šalje 8-bitni podatak za upis u registar
  • A/NA (bit 9) – SLAVE uređaj šalje potvrdu upisa (A – acknowledge)
  • STOP – MASTER za kraj komunikacije inicira obrnuti prijelaz od START, odnosno prijelaz SDA iz logičke nule u logičku jedinicu za vrijeme dok je SCL na logičkoj jedinici

Sve je ovo lijepo, međutim glede našeg specifičnog čipa probleme možemo očekivati u definiranju točnog načina i redoslijeda na koji se zapisuju podaci na čip, odnosno u organizaciji popunjavanja REGISTER BIT <7:0> polja. Kineska dokumentacija nije baš detaljna glede tih objašnjenja, u nekim dijelovima je nedorečena, a priloženi kod u C programskom jeziku je samo informativan.  Bio bi najsretniji kad bih mogao iščitati podatke upisane u registru i usporediti ih sa podacima koji su dani u dokumentaciji.

 

Organizacija podataka u registrima čipa HS6760

Nekako sam uspio prevesti kineske znakove do te mjere da mogu donekle shvatiti organizaciju podataka u registrima. Zapravo, ovo vjerojatno i nisu nužno registri nego podatkovne tablice u koje su organizirani podaci. Dokumentacija daje podatke samo o registrima u koje korisnik može upisivati bitove za definiranje rada čipa. Također, ti podaci su nepotpuni (vjerojatno se i razlikuju kod različitih inačica čipa), no na osnovu dva dostupna datasheeta uspio sam sastaviti osnovne podatkovne tablice:

 

 

Prije nego krenemo sa pre-programiranjem našeg čipa bilo bi dobro vidjeti možemo li pročitati postojeće binarne zapise u navedenim registrima i usporediti ih sa očekivanim vrijednostima prema podatkovnim tablicama. Ovo je najlakše usporedivo sa binarnim kodom frekvencije jer sadrži niz od 14 bitova.

 

Binarno kodiranje radnih frekvencija za upis u registre

Kao što se vidi iz naše tablice, kanalna frekvencija zauzima 8 bitova registra 0x00 i prvih 6 bitova registra 0x01. Pretvaranje frekvencije u binarni niz od 14 bitova je vrlo jednostavno. Željena frekvencija u MHz se pomnoži sa 20 čime se dobije određeni decimalni broj. Taj decimalni broj se zatim pretvori u heksadecimalni ili binarni broj koji se upisuje u registre. Osam nižih (zadnjih) bitova koji predstavljaju binarni broj frekvencije se zapisuje u registar 0x00, a preostalih šest viših bitova se zapisuju u registar 0x01.

Uzmimo na primjer da želimo upisati frekvenciju 90,5 MHz:

  • 90,5 x 20 = 1810
  • 1810 pretvoreno u heksadecimalni broj je 0x0712 (binarno 00000111 00010010)
  • u registar 0x00 se upiše niži dio heksadecimalnog broja 0x12 (00010010)
  • u registar 0x01 se upiše viši dio heksadecimalnog broja 0x07 (00000111)
  • nakon što je frekvencija upisana, na najniži bit registra 0x02 (D0) treba upisati nulu, a zatim uz kašnjenje od 10 ms upisati jedinicu kako bi frekvencija bila setirana

Frekvencijski kanali za ukupno 8 radnih frekvencija koje moguće programirati u čip se vjerojatno automatski pohranjuju na predefinirane memorijske lokacije, setiranjem svakog novog upisa frekvencije.

 

Hardversko povezivanje

Hardversko povezivanje čipa HS6760 sa nekom Arduino razvojnom pločom je vrlo jednostavno. Osim napajanja (3,3 V) potrebno je još samo povezati I2C sabirnicu, odnosno linije SCK i SDA. Kod Arduino Mega 2560 ploče, SCK linija je na D21, a SDA linija je na D20. Već smo rekli da nam pull-up otpornici nisu potrebni jer su isti ugrađeni u sam čip.

  • VCC – 3V3 V
  • GND – GND
  • SDA (44 D20 Arduino Mega 2560) – SDA (pin 2 HS6760)
  • SCK (43 D21 Arduino Mega 2560) – SCK (pin 1 HS6760)

 

 

Kodiranje za razmjenu podataka preko I2C

Kod Arduino sistema za I2C komunikaciju praktično uvijek se koristi gotova programska knjižica (library) u kojoj su sadržani standardni dijelovi programskog koda za I2C i čime je onda samo programiranje uvelike olakšano. Na primjer, vidjeli smo gore na shemi I2C protokola da se početak komunikacije (START) incicira prebacivanjem SDA linije na logičku nulu u trenutku kada je SCL na logičkoj jedinici i isto završetak komunikacije (STOP) se inicira prijelazom SDA iz logičke nule u logičku jedinicu za vrijeme dok je SCL na logičkoj jedinici. To znači da je unutar ovog okvira (razmjena podataka) promjena stanja signala SDA dozvoljena samo kad je SCL na logičkoj nuli. Trebali bi napisati puno linija koda da bi osigurali samo ovaj uvjet. Stoga je bolje koristiti gotove library koje se brinu o pravilnom protokolu izmjene logičkih stanja na SCL i SDA linijama, a mi upisujemo samo naredbe za specifično čitanje ili pisanje podataka. U Arduino okružju library za I2C komunikaciju ima oznaku „Wire.h“.

Stoga u prvi redak uvijek upisujemo naredbu:

 

#include <Wire.h>

 

 

Čitanje binarnih vrijednosti unutar registara čipa HS6760

U naš čip bi trebalo biti upisano šest frekvencija sa binarnim nizovima kako slijedi:

 

Isprobali smo i modificirali nekoliko programskih kodova za čitanje podataka iz memorijskih registara. Neki su bili više uspješni od drugih, no generalno gledano, pročitani podaci ne odgovaraju očekivanima, barem ne što se tiče frekvencije.

 


 

#include <Wire.h>

byte ADDRESS_SLAVE = 0X18;
byte REGISTER_XY = 0X00;
byte READ_LENGTH = 8;

void setup()

{
Wire.begin();
Wire.setClock(115200); // set I2C speed
Serial.begin(9600);

}

void loop()

{
Wire.beginTransmission(ADDRESS_SLAVE);
Wire.write(REGISTER_XY);  // set register for read
Wire.endTransmission(false); // false to not release the line
Wire.requestFrom(ADDRESS_SLAVE,READ_LENGTH); // request bytes from register XY
byte buff[READ_LENGTH];
Wire.readBytes(buff, READ_LENGTH);
for (int i = 0; i < READ_LENGTH; i++) {
Serial.println(buff[i], BIN);

}

Serial.println();

delay(10000);

}

Provjereno funkcionalan program za čitanje vrijednosti registra čipa HS6760 i ispis u binarnom obliku. Serial Monitor unutar sučelja Arduino IDE preko kojeg čitamo podatke iz registara mora biti podešen na 9600 bauda kako je i definirano u programu. Varijablu REGISTER_XY je potrebno promijeniti za čitanje pojedinog registra. 

 

Ispis binarnih podataka sa prvih osam registra čipa HS6760 (ukupni broj registara je veći).

 

Naše binarne podatke za frekvenciju bi očekivali u prva dva stupca u registrima 0x00 i 0x01. Međutim, za sada ne mogu definirati zašto oni ne odgovaraju očekivanima. Moguće je da sam kod pisanja i testiranja raznih kodova za čitanje podataka nehotice prebrisao originalne podatke. Moguće je i da program ne čita podatke sa ispravnih adresa. Možda ovaj konkretni čip pripada nekoj seriji (inačici) koja se programira na drugačiji način. Može biti da su definirani registri 0x00, 0x01, 0x02, 0x03 i 0x07 privremeni i da se nakon setiranja ovi podaci prebacuju na neke druge adrese. Ovo posljednje ima najviše smisla jer se može upisati ukupno osam frekvencija (svaka sa 14 bitova), a sve one zasigurno ne mogu stati u dva registra.

Kako god bilo, sada ne želim nagađati, nego idemo programirati čip prema datasheetu kojeg imamo, pa ćemo ponovno iščitati registre.

 

Upis radne frekvencije u čip HS6760

 


/***********************
FREKVENCIJA KRISTALA
IZLAZNA SNAGA
NACIN RADA
***********************/

void HS6760_initial(void)

{

uint8_t RegData; // varijabla za odabir kristala i izlazne snage
#ifdef Clock_24M
RegData=0x36;//PGA=12dB,24M
#else
#ifdef Clock_12M
RegData=0x34;//PGA=12dB,12M
#else
#ifdef Clock_7v6M
RegData=0x32;//PGA=12dB,7.6M
#else
#endif
#endif
#endif

I2C0_WriteBuffer(HS6760_I2C_ID,0x02,&RegData,1);  // Upis frekvencije kristala (12 MHz = 00110<10>0) i izlazne snage (12 dB = <0011>0100) na SLAVE 0x18, registar 0x02
delay(10);

RegData=0x06;
I2C0_WriteBuffer(HS6760_I2C_ID,0x01,&RegData,1);  // Upis nacina rada: Normal mode (<00>000110) na SLAVE 0x18, registar 0x01
delay(10);

HS6760_reset();   // resetiranje chipa

}

// *********
// RESET
// *********

void HS6760_reset(void)                         //HS6760 Funkcija resetiranja čipova

{

uint8_t Data8;                                  //definiranje broja bitova
I2C0_ReadBuffer(HS6760_I2C_ID,0x07,&Data8,1);   // pozicioniranje na SLAVE 0x18, registar 0x07
Data8&=0x7f;                                    // Vrijednost je <0>1111111
I2C0_WriteBuffer(HS6760_I2C_ID,0x07,&Data8,1);  // upisivanje bitova <0>1111111 (hex 0x7f) na SLAVE 0x18, registar 0x07
delay(10);                                   // pauza 10 ms
Data8|=0x80;                                    // Vrijednost je <1>0000000
I2C0_WriteBuffer(HS6760_I2C_ID,0x07,&Data8,1);  // upisivanje bitova <1>0000000 (hex 0x80) na SLAVE 0x18, registar 0x07

}

/**************************************************
Function: HS6760_SetFreq()
Parameter: curFreq: FM frequency *10 ,such as 1017,933,1077..
Description: set FM to a frequency
**************************************************/

void HS6760_SetFreq(uint16_t curFreq=270) // varijabla "curFreq" kao vrijednost frekvencije MHz x 10 (27 MHz)

{

uint16_t curChan;                    // definiranje broja bitova za varijablu "curChan"
uint8_t Data8bit;                    // definiranje broja bitova za varijablu "Data8bit"
uint8_t TmpData8bit[2];              // kreiranje privremenog binarnog niza
curChan=curFreq*2;                   //pretvaranje frekvencije u decimalnu vrijednost
TmpData8bit[0]=curChan>>8;           //definiranje pozicije zapisa viših bitova
TmpData8bit[1]=curChan&0xff;         // definiranje pozicije zapisa nižih bitova
I2C0_WriteBuffer(HS6760_I2C_ID,0x01,&TmpData8bit[0],1);  // upisivanje viših bitova u registar 0x01
delay(10);                                            // pauza 10 ms

I2C0_WriteBuffer(HS6760_I2C_ID,0x00,&TmpData8bit[1],1);  // upisivanje nižih bitova u registar 0x00
delay(10);                                            // pauza 10 ms

I2C0_ReadBuffer(HS6760_I2C_ID,0x02,&Data8bit,1);   // pozicioniranje na SLAVE 0x18, registar 0x02
Data8bit&=0xfe;                                    // definiranje zapisa sa najnižim bitom 0 (1111111<0>)
I2C0_WriteBuffer(HS6760_I2C_ID,0x02,&Data8bit,1);  // upisivanje vrijednosti u registar 0x02
delay(10);                                      // pauza 10 ms

Data8bit|=0x01;                                    // definiranje zapisa sa najnižim bitom 1 (0000000<1>)
I2C0_WriteBuffer(HS6760_I2C_ID,0x02,&Data8bit,1);  // upisivanje vrijednosti u registar 0x02
delay(10);                                          // pauza 10 ms

}

int main()  // pozivanje programa za upisivanje slijedeće frekvencije

{

HS6760_initial();

HS6760_SetFreq(270);  // Postavi frekvenciju na 27,0 MHz

HS6760_SetPow(31);  // Postavi izlaznu snagu na maksimalnu

}



/**************************************************
Function: HS6760_SetPower(uint8_t num)
Parameter: num=1~31 (Decimalism)
curFreq: FM power dBm ,such as 1、2、…… 31
Description: set FM to a Power (FCC test)
**************************************************/


void HS6760_SetPow(uint8_t num)  // program za upis izlazne snage (FCC test)

{

uint8_t Data8;                   // definiranje broja bitova za varijablu "Data8"
I2C0_ReadBuffer(HS6760_I2C_ID,0x07,&Data8,1);   // pozicioniranje na SLAVE 0x18, registar 0x07
Data8&=0xe0;                                    // definiranje zapisa sa 5 najniža bita (111<00000>)
Data8+=num;                                     // povećanje vrijednosti zapisa za 1 - 31
I2C0_WriteBuffer(HS6760_I2C_ID,0x07,&Data8,1);  // upisivanje vrijednosti u registar 0x07

HS6760_reset();  // reset

}


/**************************************************
Function: FCC_test(uint8_t fre)
Parameter: fre:such as test_88v1 /test_98v1 /test_107v9
Description: set FM to a power according to frequency
**************************************************/

void FCC_test(uint8_t fre)  // program za upis frekvencije (FCC test)

{

switch (fre)

{

case 0: HS6760_SetFreq(881);HS6760_SetPow(1);break;
case 1: HS6760_SetFreq(981);HS6760_SetPow(2);break;
case 2: HS6760_SetFreq(1079);HS6760_SetPow(3);break;
default:break;

}

}

int main()

{

HS6760_initial();

FCC_test(test_88v1);

HS6760_Fre_dev();

}


/**************************************************
Function: frekvencijska devijacija
**************************************************/

void HS6760_Fre_dev(void)

{

uint8_t Data8;
I2C0_ReadBuffer(HS6760_I2C_ID,0x03,&Data8,1);  // pozicioniranje na SLAVE 0x18, registar 0x03
Data8&=0xfc; // definiranje zapisa 111111<00> sa najnižim bitovima 00
Data8|=0x02; // definiranje zapisa 000000<10> sa najnižim bitovima 01 (FM devijacija 22,5 kHz)
I2C0_WriteBuffer(HS6760_I2C_ID,0x03,&Data8,1); // upisivanje vrijednosti u registar 0x03

}



 

Ovo je načelni program iz tvorničkog datasheeta čipa HS6760 za upisivanje parametara rada čipa u odgovarajuće registre. Program je pisan u C jeziku. Arduino platforma koristiti vrlo sličan programski jezik, no neke naredbe su različite, pogotovo ako koristimo specifične library datoteke.

S obzirom da nisam stručnjak u C programskom jeziku (kao ni u jednom drugom), napisao sam općenite komentare (vođen nekom logikom) koji mi pomažu (nadam se) u njegovom razumijevanju. Program sadrži nekoliko potprograma:

  1. upisivanje bitova za definiranje frekvencije rada kristala i izlazne RF snage u registru 0x02
  2. upisivanje bitova za definiranje načina rada čipa u registru 0x01
  3. resetiranje čipa u registru 0x07
  4. upisivanje viših 6 bita za definiranje izlazne radne frekvencije u registru 0x01
  5. upisivanje nižih 8 bita za definiranje izlazne radne frekvencije u registru 0x00
  6. setiranje radne frekvencije u registru 0x02
  7. koraci 4-6 se ponavljaju osam puta za osam radnih frekvencija
  8. slijede dva potprograma za definiranje radnih frekvencija i izlazne snage u svrhu testiranja da li izlazni signal zadovoljava FCC/CE standarde
  9. resetiranje čipa u registru 0x07
  10. upisivanje bitova za definiranje devijacije frekvencije u registru 0x03

Međutim, ovi programski kodovi posve sigurno neće raditi sami po sebi kako su napisani, nego je potrebno dovršiti program popunjavanjem zaglavlja (header file) i vjerojatno nekim drugim standardnim programskim rutinama. Tu je vjerojatno potrebno uključiti određene predefinirane library datoteke za C programski jezik (isto kao što to radimo i za Arduino). To je moguće library naziva „stdint.h“ koji podržava naredbe za određivanje broja bitova i library naziva “stdio.h” koji podržava Tmp funkcije sadržane u programskom kodu. Također je vrlo vjerojatno u zaglavlju potrebno definirati i neke varijable koje se koriste u programu. Kako god bilo, iako je program očito vrlo jednostavan za nekog tko ima osnovna znanja programiranja u C-u, ja bih morao učiti od nule kako ispravno popuniti zaglavlje ovog programa. Praktičnije mi je učiti programiranje na Arduino platformi za koju na Internetu ima puno više primjera i objašnjenja.

Stoga ćemo mi pokušati napisati jednostavan program na Arduino platformi koji će izravno upisati gotove bajtove (serija od 8 bita) na određene registre našeg čipa i naravno izvršiti potrebna setiranja i resetiranja.

 

 

Ovdje smo napravili pregledni prikaz kako su određeni parametri rada čipa zapisani u registre kako bi lakše pisali tijek programa.

S obzirom da raspolaganju imamo samo jedan čip, programiranju ćemo pristupiti nešto opreznije. Za početak ću preskočiti rutinu za resetiranje čipa i pokušati samo prebrisati postojeće registre koji sadrže informacije o parametrima rada čipa.

 


// programiranje parametara na kineski chip HS 6760

#include <Wire.h>  // ucitavanje I2C Wire library

void setup() {  // pocetak programskog koda
Serial.begin(9600); // brzina serijske komunikacije
Wire.begin();  // naredba za početak I2C komunikacije


// upisivanje frekvencije 27 MHz u binarnom obliku 00000010 00011100 (hex 0x1C + 0x02)

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x00);             // pozicioniranje na registar 0x00 chipa HS6760
Wire.write(0x1C);             // upisivanje bitova 00011100 (hex 0x1C)
Wire.endTransmission();       // završetak komunikacije

delay(10);  // pauza 10 ms

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x01);             // pozicioniranje na registar 0x01 chipa HS6760
Wire.write(0x02);             // upisivanje bitova 00000010 (hex 0x02)
Wire.endTransmission();       // završetak komunikacije

delay(10);  // pauza 10 ms

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x02);             // pozicioniranje na registar 0x02 chipa HS6760
Wire.write(0xF4);             // upisivanje bitova 11110100 (hex 0xF4)
Wire.endTransmission();       // završetak komunikacije

delay(10);  // pauza 10 ms

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x02);             // pozicioniranje na registar 0x02 chipa HS6760
Wire.write(0xF5);             // upisivanje bitova 11110101 (hex 0xF5)
Wire.endTransmission();       // završetak komunikacije

delay(10);  // pauza 10 ms

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x03);             // pozicioniranje na registar 0x03 chipa HS6760
Wire.write(0x02);             // upisivanje bitova 00000010 (hex 0x02)
Wire.endTransmission();       // završetak komunikacije

delay(10);  // pauza 10 ms

} // zavrsetak programskog koda za upis frekvencije


void loop() {

// put your main code here, to run repeatedly:

}

 


 

Nakon upisa bitova preko ovog programa, ponovno sam pročitao binarne podatke sa registra.

 

 

Kao što se vidi, naša četiri upisana bajta sada se točno prikazuju u prva četiri stupca registra 0x00.

Sada samo treba provjeriti da li ovo funkcionira u praksi, odnosno da li je naš čip još uvijek živ.

Glede toga, ima dobra i loša vijest. Dobra vijest je da je čip živ, no loša vijest je da ne radi na frekvenciji 27 MHz, nego i dalje na svojih osam tvorničkih frekvencija:

  • 87,5 MHz
  • 88,1 MHz
  • 88,3 MHz
  • 88,5 MHz
  • 88,7 MHz
  • 40,0 MHz
  • 64,0 MHz
  • 76,0 MHz

Iz ovoga smo naučili dvije stvari. Modul sa čipom HS6760 koji se prodaje na Internetu zapravo sadrži tvornički programiran čip na gornjih osam frekvencija. U podacima se ne navode frekvencije od 40 MHz i 64 MHz jer su izvan komercijalnih UKV FM opsega. Također, niti na jednoj slici ovog modula na Internetu nećete vidjeti koji čip je ugrađen, niti se to bilo gdje spominje. Ja sam ovaj modul kupio jer je jeftin i činio mi se zanimljiv za proučavanje.

Druga stvar koju sada znamo, to je da su registri za upis frekvencije privremeni. Nakon što se bitovi za određenu frekvenciju upišu u registre 0x01 i 0x02, oni će setiranjem biti pohranjeni na druge adrese.

S obzirom da promjena frekvencije nije uspjela, promijenio sam bitove koji se šalju za setiranje frekvencije na način kako je to napravljeno i u originalnom programu. Naime, ja sam prvo mijenjao bitove 11110100 u 11110101 kako bi automatski ostala upisana izlazna snaga i frekvencija kristala. U drugom pokušaju mijenjao sam bitove 11111110 u 00000001 kako je i u originalnom programu. Iako se u oba slučaja najniži bit jednako mijenja (0 -> 1), ovo je ipak učinilo neki pomak. Naime, nakon čitanja podataka iz registra sada više nisu vidljivi upisani podaci kao u prethodna dva pokušaja, nego oni koje smo čitali i kod originalno programiranog čipa. Nešto se očito resetiralo, međutim, ni to nije promijenilo niti jednu radnu frekvenciju.

Razlog za ovo sada može jedino biti obavezan RESET čipa. Naime, nove podatke u memorijske registre vjerojatno ne možemo upisivati prije nego se prethodno obrišu stari podaci. U mojem posljednjem prokušaju, frekvencija je upisana i setirana, međutim ona ipak nije bila nigdje pohranjena jer jednostavno nije bilo praznog memorijskog mjesta za tu pohranu. Stoga ćemo prepraviti naš program tako da uključuje i RESET čipa.

 


 

// programiranje parametara na kineski chip HS 6760

#include <Wire.h>  // ucitavanje I2C Wire library

void setup() {  // pocetak programskog koda
Serial.begin(9600); // brzina serijske komunikacije
Wire.begin();  // definiranje MASTER uredjaja


// upisivanje bitova za definiranje frekvencije rada kristala i izlazne RF snage u registru 0x02 (11110100)

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x02);             // pozicioniranje na registar 0x00 chipa HS6760
Wire.write(0xF4);             // upisivanje bitova 11110<10>0 (hex 0xF4)
Wire.endTransmission();       // zavrsetak komunikacije


//Upis nacina rada: Normal mode (<00>000110) na SLAVE 0x18, registar 0x01

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x01);             // pozicioniranje na registar 0x01 chipa HS6760
Wire.write(0x06);             // upisivanje bitova <00>000110 (hex 0x06)
Wire.endTransmission();       // zavrsetak komunikacije


//RESET (<00>000110) na SLAVE 0x18, registar 0x07 (najviši bit)

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x07);             // pozicioniranje na registar 0x07 chipa HS6760
Wire.write(0x7F);             // upisivanje bitova <0>1111111 (hex 0x7F)
Wire.endTransmission();       // zavrsetak komunikacije

delay(10);  // pauza 10 ms

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x07);             // pozicioniranje na registar 0x07 chipa HS6760
Wire.write(0x80);             // upisivanje bitova <1>0000000 (hex 0x80)
Wire.endTransmission();       // zavrsetak komunikacije

delay(10);  // pauza 10 ms



// upisivanje frekvencije 27 MHz u binarnom obliku 00000010 00011100 (hex 0x1C + 0x02)

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x00);             // pozicioniranje na registar 0x00 chipa HS6760
Wire.write(0x1C);             // upisivanje bitova 00011100 (hex 0x1C)
Wire.endTransmission();       // zavrsetak komunikacije

delay(10);  // pauza 10 ms

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x01);             // pozicioniranje na registar 0x01 chipa HS6760
Wire.write(0x02);             // upisivanje bitova 00000010 (hex 0x02)
Wire.endTransmission();       // završetak komunikacije

delay(10);  // pauza 10 ms

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x02);             // pozicioniranje na registar 0x02 chipa HS6760
Wire.write(0xF4);             // upisivanje bitova 1111111<0> (hex 0xFE)
Wire.endTransmission();       // zavrsetak komunikacije

delay(10);  // pauza 10 ms

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x02);             // pozicioniranje na registar 0x02 chipa HS6760
Wire.write(0xF5);             // upisivanje bitova 0000000<1> (hex 0x01)
Wire.endTransmission();       // zavrsetak komunikacije

delay(10);  // pauza 10 ms



// upisivanje Frekvencijske devijacije

Wire.beginTransmission(0x18); // pocetak komunikacije sa chipom HS6760 na SLAVE adresi 0x18
Wire.write(0x03);             // pozicioniranje na registar 0x03 chipa HS6760
Wire.write(0x02);             // upisivanje bitova 00000010 (hex 0x02)
Wire.endTransmission();       // zavrsetak komunikacije


} // zavrsetak programskog koda

void loop() {

// put your main code here, to run repeatedly:

}

 

 

Iako moj program (nadam se) slijedi proceduru zapisa prema originalnom programu, svejedno, čip se ne resetira i stalno radi kao i prije na svojim tvorničkim postavkama.

Očito da mora postojati neka dodatna procedura kod upisa registara koju ja ne znam iščitati iz originalnog C programa ili moj kod za Arduino nije onakav kakav bi trebao biti…

 

Leave a comment

Vaša adresa e-pošte neće biti objavljena. Obavezna polja su označena sa *