STM32, seriālais I2C interfeiss. STM32, seriālā interfeisa I2C Stm32 interfeisa i2c apraksts turpinājums

Dažiem garšo pīrāgi, kādam nē.

I2c saskarne ir plaši izplatīta un izmantota. Programmā stm32f4 ir pat trīs moduļi, kas ievieš šo protokolu.
Protams, ar pilnīgs atbalsts visa šī lieta.

Darbs ar moduli kopumā ir tāds pats kā citos kontrolleros: jūs tam dodat komandas, tas izpilda tās un ziņo par rezultātu:
I> Mēs devāmies SĀKT.
S> Labi, nosūtīju.
Es> Forši, nosūtiet adresi tūlīt. Tāpat kā šis: 0xXX.
S> Labi, nosūtīju. Man teica, ka ACK. Ejam tālāk.
I> Joprojām dzīvs, labi. Šeit ir reģistra numurs: 0xYY, - iesim.
S> Nosūtīts, saņemts ACK.
I> Tagad nosūtiet viņam datus, šeit ir baits: 0xZZ.
S> Nosūtīts, viņš piekrīt vairāk: ACK.
I> Izdrāž viņu, vēl ne. Viņi devās STOP.
S> Labi.

Un viss ir aptuveni tādā garā.

IN šis kontrolieris i2c tapas ir izkaisītas pa portiem šādi:
PB6: I2C1_SCL
PB7: I2C1_SDA

PB8: I2C1_SCL
PB9: I2C1_SDA

PB10: I2C2_SCL
PB11: I2C2_SDA

PA8: I2C3_SCL
PC9: I2C3_SDA
Kopumā ir ērti apskatīt perifērijas ierīču spraudni 59. lpp.

Pārsteidzoši, lai strādātu ar i2c, ir nepieciešami visi tā reģistri, par laimi no tiem ir maz:
I2C_CR1- komandas uz moduli komandu/stāvokļu nosūtīšanai un darbības režīmu izvēlei;
I2C_CR2- DMA iestatīšana un moduļa darbības frekvences norādīšana (2-42 MHz);
I2C_OAR1- ierīces adreses iestatīšana (pakalpojumam), adreses lielums (7 vai 10 biti);
I2C_OAR2- ierīces adreses iestatīšana (ja ir divas adreses);
I2C_DR- datu reģistrs;
I2C_SR1- moduļa statusa reģistrs;
I2C_SR2- statusa reģistrs (slave, jālasa, ja SR1 ir iestatīti karodziņi ADDR vai STOPF);
I2C_CCR- interfeisa ātruma iestatīšana;
I2C_TRISE- malu laika iestatīšana.

Tomēr puse no tiem ir “pieraksti un aizmirsti” tipa.

STM32F4-Discovery platei jau ir I2C ierīce, ar kuru var trenēties: CS43L22, audio DAC. Tas ir savienots ar tapām PB6/PB9. Galvenais neaizmirst pielikt PD4 pinam augstu līmeni (tur sēž ~RESET), citādi DAC nereaģēs.

Iestatīšanas procedūra ir aptuveni šāda:
1 . Atļaut pieslēgvietas un paša moduļa pulksteni.
Mums ir nepieciešami tapas PB6/PB9, tāpēc mums ir jāiestata 1. bits (GPIOBEN) RCC_AHB1ENR reģistrā, lai iespējotu portu.
Un iestatiet bitu 21 (I2C1EN) RCC_APB1ENR reģistrā, lai iespējotu I2C moduli. Otrajam un trešajam modulim bitu skaitļi ir attiecīgi 22 un 23.
2 . Pēc tam tiek konfigurētas tapas: Oped Drain izeja (GPIO->OTYPER), alternatīvais funkcijas režīms (GPIO->MODER) un alternatīvais funkcijas numurs (GPIO->AFR).
Ja vēlaties, varat konfigurēt pievilkšanos (GPIO->PUPDR), ja tā nav uz tāfeles (un jebkura veida ir nepieciešama pievilkšanās abu līniju barošanas avotam). I2C numurs vienmēr ir vienāds: 4. Ir jauki, ka katram perifērijas veidam ir atsevišķs numurs.
3 . Fpclk1 perifērijas pašreizējā pulksteņa frekvence (izteikta MHz) ir norādīta CR2 reģistrā. Kā es saprotu, tas ir nepieciešams, lai aprēķinātu dažādus protokolu laikus.
Starp citu, tam vajadzētu būt vismaz diviem parastajam režīmam un vismaz četriem ātrajam režīmam. Un, ja jums ir nepieciešams pilns ātrums 400 kHz, tad tas arī jādala ar 10 (10, 20, 30, 40 MHz).
Maksimālā pieļaujamā takts frekvence: 42 MHz.
4 . Interfeisa ātrums ir konfigurēts CCR reģistrā, un režīms ir atlasīts (parasts/ātrs).
Nozīme ir šāda: Tsck = CCR * 2 * Tpckl1, t.i. SCK periods ir proporcionāls CCR (ātrajam režīmam viss ir nedaudz sarežģītāks, bet tas ir aprakstīts RM).
5 . Maksimālais pieaugošās malas laiks TRISE reģistrā tiek regulēts. Standarta režīmā šis laiks ir 1 µs. Reģistrā jāieraksta autobusu ciklu skaits, kas atbilst šim laikam, plus viens:
ja Tpclk1 cikls ilgst 125 ns, tad ierakstiet (1000 ns / 125 ns) + 1 = 8 + 1 = 9.
6 . Pēc izvēles ir iespējota pārtraukumu signālu (kļūdu, statusa un datu) ģenerēšana;
7 . Modulis ieslēdzas: PE karodziņš CR1 reģistrā ir iestatīts uz 1.

Tad modulis darbojas kā nākas. Jums vienkārši jāievieš pareizā komandu secība un jāpārbauda rezultāti. Piemēram, reģistra ieraksts:
1 . Vispirms jānosūta START, CR1 reģistrā iestatot karogu ar tādu pašu nosaukumu. Ja viss ir ok, tad pēc kāda laika SR1 reģistrā tiks uzstādīts SB karogs.
Vēlos atzīmēt vienu momentu - ja uz līnijas nav pievilkšanās (un tie ir uz 0), tad šis karogs var arī negaidīt.
2 . Ja karodziņš ir saņemts, tad nosūtām adresi. Septiņu bitu adresei mēs to vienkārši ierakstām DR tieši tā, kā tā būs rindā (7 adreses biti + virziena bits). Desmit bitiem sarežģītāks algoritms.
Ja ierīce uz adresi atbild ar ACK, tad SR1 reģistrā parādīsies karogs ADDR, ja nē, tad parādīsies karogs AF (Acknowledge error).
Ja parādās ADDR, jums ir jāizlasa SR2 reģistrs. Jums tur nekas nav jāskatās, tikai secīga SR1 un SR2 nolasīšana atiestata šo karogu. Un, kamēr karodziņš ir iestatīts, galvenais SCL notur zemu, kas ir noderīgi, ja ir jālūdz attālajai ierīcei pagaidīt pirms datu nosūtīšanas.
Ja viss ir kārtībā, modulis pēc tam pārslēgsies uz datu saņemšanas vai pārsūtīšanas režīmu atkarībā no nosūtītās adreses vismazāk nozīmīgā bita. Rakstīšanai tam jābūt nullei, lasīšanai - vienam.
bet mēs skatāmies ierakstu, tāpēc pieņemsim, ka tur bija nulle.
3 . Tālāk nosūtām mūs interesējošā reģistra adresi. Tādā pašā veidā to pierakstot DR. Pēc pārsūtīšanas tiek iestatīti karodziņi TXE (pārsūtīšanas buferis ir tukšs) un BTF (pārsūtīšana pabeigta).
4 . Tālāk nāk dati, kurus var nosūtīt, kamēr ierīce atbild ar ACK. Ja atbilde ir NACK, šie karodziņi netiks iestatīti.
5 . Pabeidzot pārsūtīšanu (vai neparedzēta stāvokļa gadījumā), mēs nosūtām STOP: tāda paša nosaukuma karodziņš ir iestatīts CR1 reģistrā.

Lasot viss ir pa vecam. Izmaiņas tikai pēc reģistra adreses uzrakstīšanas.
Tā vietā, lai rakstītu datus, START tiek nosūtīts vēlreiz (restartēt), un adrese tiek nosūtīta ar vismazāko bitu kopu (lasīšanas zīme).
Modulis gaidīs datus no ierīces. Lai mudinātu to nosūtīt nākamos baitus, pirms saņemšanas CR1 ir jāiestata ACK karodziņš (lai modulis pēc saņemšanas nosūtītu to pašu ACK).
Kad tas apniks, noņemiet karogu, ierīce redzēs NACK un apklusīs. Pēc tam parastajā kārtībā nosūtām STOP un priecājamies par saņemtajiem datiem.

Lūk, tas pats koda formā:
// Moduļa inicializēšana void i2c_Init(void) ( uint32_t Clock = 16000000UL; // Moduļa pulksteņa frekvence (netiek izmantots system_stm32f4xx.c) uint32_t Ātrums = 100000UL; // ports 100 kHB CC // Enable GHB CC |= RCC_AHB1ENR_GPIOBEN; // Iestatīt tapas PB6, PB9 // Atveriet aizplūšanu! GPIOB->OTYPER |= GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_9; // Pievilkšanās ir ārēja, tāpēc to šeit nevar konfigurēt! // ja nepieciešams, skatiet GPIOB->PUPDR reģistru // Alternatīvās GPIOB funkcijas numurs ->AFR &= ~(0x0FUL<< (6 * 4)); // 6 очистим GPIOB->AFR |= (0x04UL<< (6 * 4)); // В 6 запишем 4 GPIOB->AFR &= ~(0x0FUL<< ((9 - 8) * 4)); // 9 очистим GPIOB->AFR |= (0x04UL<< ((9 - 8) * 4)); // В 9 запишем 4 // Режим: альтернативная функция GPIOB->MODER &= ~((0x03UL<< (6 * 2)) | (0x03UL << (9 * 2))); // 6, 9 очистим GPIOB->MODER |= ((0x02UL<< (6 * 2)) | (0x02UL << (9 * 2))); // В 6, 9 запишем 2 // Включить тактирование модуля I2C1 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // Šajā brīdī I2C ir jāizslēdz // Atiestatīt visu (SWRST == 1, atiestatīt) I2C1->CR1 = I2C_CR1_SWRST; // PE == 0, tas ir galvenais I2C1->CR1 = 0; // Mēs pieņemam, ka mēs darbojamies no RC (16 MHz) // Pulksteņu sistēmā nav priekšskaleru (visi 1) // Draudzīgā veidā mums tas viss jāaprēķina no // moduļa faktiskās takts frekvences I2C1->CR2 = Pulkstenis / 1000000UL; // 16 MHz // Pielāgojiet frekvenci ( // Tclk = (1 / Fperiph); // Augšstilba = Tclk * CCR; // Tlow = Augšstilba; // Fi2c = 1 / CCR * 2; // CCR = Fperiph // ( Fi2c * 2); uint16_t Vērtība = (uint16_t) (Pulkstenis / (Ātrums * 2)); // Minimālā vērtība: 4 if(Vērtība< 4) Value = 4; I2C1->CCR = vērtība; ) // Iestatīt limita pieauguma laiku // Standarta režīmā šis laiks ir 1000 ns // Mēs vienkārši pievienojam vienu frekvencei, kas izteikta MHz (sk. RM 604. lpp.). I2C1->TRISE = (Pulkstenis / 1000000UL) + 1; // Iespējot moduli I2C1->CR1 |= (I2C_CR1_PE); // Tagad jūs varat kaut ko darīt (); // Reģistrēt adresi if(!i2c_SendData(Register)) return i2c_SendStop(); // Dati if(!i2c_SendData(Data)) return i2c_SendStop(); // Stop! i2c_SendStop(); return true; ) // Saņemt baitu bool i2c_ReceiveByte(uint8_t Adrese, uint8_t Reģistrēties, uint8_t * Dati) ( if(!i2c_SendStart()) return false; // Chip address if(!i2c_SendAddress(Address)) return i2c_SendStop(); // Reģistrēt adresi if(! i2c_SendData(Register)) return i2c_SendStop(); // Restart if(!i2c_SendStart()) return false; // Chip adrese (lasīt) if(!i2c_SendAddress(Address | 1)) return i2c_SendStop(); // Saņemt baitu if(!i2c_ReceiveData(Data)) return i2c_SendStop(); // Stop! i2c_SendStop(); return true; ) Lietojums: ( uint8_t ID = 0; i2c_Init(); // Mēs pieņemam, ka PD4 ir iestatīts augstā līmenī un DAC darbojas (tas kaut kā jādara) // Nosūtiet baitu uz ierīci ar adresi 0x94, lai reģistrētu 0x00 ar vērtību 0x00. i2c_SendByte(0x94, 0x00, 0x00); // Saņemt baitu no ierīces ar adresi 0x94 no reģistra 0x01 (ID) mainīgā buferī i2c_ReceiveByte(0x94, 0x01, &ID); )
Protams, jūs to nevarat izdarīt, izņemot apmācības piemēru. Gaidīšana, līdz darbība tiks pabeigta, ir pārāk ilga tik ātram kontrolierim.

(Izstrādātāja rokasgrāmata HCS08 ģimenes mikrokontrolleriem)

Lai kontrolētu I2C moduli, tiek izmantoti 6 īpašie funkciju reģistri:

  • IICC - pirmais I2C moduļa vadības reģistrs;
  • IICC2 - I2C moduļa otrais vadības reģistrs;
  • IICS - I2C moduļa statusa reģistrs;
  • IICF - I2C moduļa bodu ātruma reģistrs;
  • IICA - I2C moduļa adrešu reģistrs;
  • IICD ir I2C moduļa datu reģistrs.

QE sērijas MCU satur 2 I2C moduļus un attiecīgi divus katra veida vadības reģistrus. Piemēram, pirmais statusa reģistrs ir IIC1S, bet otrais statusa reģistrs ir IIC2S.

11.2.8.1. IICC kontroles reģistrs

MK sērijas AC. AW, Dx, EL, GB, GT, JM, LC, QE. Q.G. SG, SH, SL
Reģistrēties Režīms D7 D6 D5 D4 D3 D2 D1 D0
IICC Lasīšana IICEN IICIE MST TX TXAK 0 0 0
Ieraksts RSTA
Atiestatīt 0 0 0 0 0 0 0 0
Bitu apraksts:
Bita nosaukums Apraksts Simbols C valodā
IICEN I2C moduļa iespējošanas bits:
0 — I2C kontrolleris ir atspējots;
1 — I2C kontrolleris ir iespējots.
bIICEN
IICIE Moduļa pārtraukuma iespējošanas bits no I2C:
0 - I2C pieprasījuma pārtraukumi ir atspējoti;
1 — ir iespējoti I2C pieprasījuma pārtraukumi.
bHCIE
MST I2C kontrollera darbības režīma izvēles bits:
0 - I2C kontrolleris darbojas Slave režīmā;
1 - I2C kontrolleris darbojas Master režīmā.
Kad šis bits mainās no 0 uz 1, tiek ģenerēts sākuma stāvoklis. Un otrādi, kad bits mainās no 1 uz 0, tiek ģenerēts Stop nosacījums.
bMST
TX Pārraides virziena izvēles bits SDA datu līnijā:
0 — līnija darbojas ievadei;
1 - līnija darbojas izvadei.
bTX
TXAK Apstiprinājuma bits saņemšanas režīmā:
0 - pēc baita saņemšanas tiek ģenerēts apstiprinājuma bits;
1 - tiek ģenerēts neapstiprināts baita bits.
Šis bits kontrolē apstiprinājuma bita ģenerēšanu pēc datu baita saņemšanas neatkarīgi no tā, vai tas ir pakārtotais vai galvenais.
bTXAK
RSTA Ja I2C modulis darbojas galvenā režīmā, šim bitam ierakstot 1, tiek atjaunots stāvoklis Sākt - “Restartēt”. bRSTA

11.2.8.2. IICS statusa reģistrs

MK sērijai AC, AW, Dx, EL, GB, GT, JM, LC, QE, QG, SG, SH, SL
Reģistrēties Režīms D7 D6 D5 D4 D3 D2 D1 D0
IICS Lasīšana TCF IAAS AIZŅEMTS ARBL 0 SRW IICIF RXAK
Ieraksts
Atiestatīt 0 0 0 0 0 0 0 0
Bitu apraksts:
Bita nosaukums Apraksts Simbols C valodā
TCF Apmaiņas pabeigšanas bits. Iestatīt pēc viena baita apmaiņas pabeigšanas:
0 — apmaiņa nav pabeigta;
1 - maiņa pabeigta.
TCF karodziņš tiek notīrīts līdz 0, kad tiek nolasīts IICD datu reģistrs (saņemšanas režīmā) vai kad tiek ierakstīts IICD datu reģistrs (pārraides režīmā).
bTCF
IAAS Vergu adreses karodziņš. Iestatīt, vai ierīce darbojas pakārtotā režīmā un galvenā ziņojumā nosūtītā adrese ir vienāda ar pakārtoto adresi, kas tiek saglabāta IICA adrešu reģistrā.
Karogs tiek notīrīts, rakstot uz IICC reģistru.
bIAAS
AIZŅEMTS Aizņemtās līnijas karogs. Šis karodziņš ir iestatīts, ja I2C modulis ir atpazinis līnijas sākuma bitu. Karogs tiek notīrīts, kad modulis nosaka līnijas stopbitu.
0 — I2C kopne ir bezmaksas;
1 — I2C autobuss ir aizņemts.
b Aizņemts
ARBL Šķīrējtiesas zaudējuma karogs:
0 - nav pārkāpumu I2C kopnes darbībā;
1 – ir šķīrējtiesas zaudējums. I2C modulim kādu laiku jāpagaida un pēc tam atkal jāsāk pārsūtīšanas darbība.
BARBL
SRW Vergu pārraides virziena bits. Šis bits norāda R/W bita stāvokli adreses laukā:
0 - vergs pieņem. Vadītājs nodod vergam;
1 - vergu raidītāji. Vadītājs saņem no verga.
bSRW
IICIF Neapkalpoto pārtraukumu pieprasījumu karodziņš I2C modulim. Iestatiet uz 1, ja ir iestatīts kāds no karodziņam: TCF, IAAS vai ARBL.
0 - nav neapkalpotu pārtraukumu;
1 - ir neapkalpoti pārtraukumi.
Karogs tiek atiestatīts, ierakstot tam 1.
bIICIF
RXAK Galvenā apstiprinājuma bits:
0 — vergu apstiprināta datu saņemšana;
1 — vergs neatzina datu saņemšanu.
Šis bits atspoguļo ASK lauka stāvokli apmaiņas laika diagrammā.
bRXAK

11.2.8.3. IICA adrešu reģistrs

Reģistrēties Režīms D7 D6 D5 D4 D3 D2 D1 D0
IICA Lasīšana ADDR
Ieraksts
Atiestatīt 0 0 0 0 0 0 0 0

Šajā reģistrā tiek saglabāta izstrādātāja piešķirtā 7 bitu pakārtotā adrese šo ierīci izstrādājot sistēmu. Šī adrese tiek automātiski salīdzināta ar adreses kodu, ko vergs saņēma adreses laukā I2C kopnē. Ja adreses sakrīt, tiek iestatīts IAAS bits IICS statusa reģistrā.

11.2.8.4. IICF datu pārraides ātruma reģistrs

MK sērijai AC, AW, Dx, EL, GB, GT, JM, LC, QE, QG, SG, SH, SL
Reģistrēties Režīms D7 D6 D5 D4 D3 D2 D1 D0
IICF Lasīšana MULT ICR
Ieraksts
Atiestatīt 0 0 0 0 0 0 0 0
Bitu apraksts:

Koeficientu SCL_DIV un SDA_HV vērtības

ISR SCL_DIV SDA_HV ISR SCL_DIV SDA_HV
0x00 20 7 0x20 160 17
0x01 22 7 0x21 192 17
0x02 24 8 0x22 224 33
0x03 26 8 0x23 256 33
0x04 28 9 0x24 288 49
0x05 30 9 0x25 320 49
0x06 34 10 0x26 384 65
0x07 40 10 0x27 480 65
0x08 28 7 0x28 320 33
0x09 32 7 0x29 384 33
0x0A 36 9 0x2A 448 65
0x0B 40 9 0x2B 512 65
0x0C 44 11 0x2C 576 97
0x0D 48 11 0x2D 640 97
0x0E 56 13 0x2E 768 129
0x0F 68 13 0x2F 960 129
0x10 48 9 0x30 640 65
0x11 56 9 0x31 768 65
0x12 64 13 0x32 896 129
0x13 72 13 0x33 1024 129
0x14 80 17 0x34 1152 193
0x15 88 17 0x35 1280 193
0x16 104 21 0x36 1536 257
0x17 128 21 0x37 1920 257
0x18 80 9 0x38 1280 129
0x19 96 9 0x39 1536 129
0x1A 112 17 0x3A 1792 257
0x1B 128 17 0x3B 2048 257
0x1C 144 25 0x3C 2304 385
0x1D 160 25 0x3D 2560 385
0x1E 192 33 0x3E 3072 513
0x1F 240 33 0x3F 3840 513

Šajā reģistrā tiek saglabāti divi bitu lauki, kas nosaka I2C apmaiņas ātrumu un laika parametrus. Sinhronizācijas signālu frekvenci nosaka pēc formulas:

SDA_hold_time datu iestatīšanas laiks I2C kopnē ir laika intervāls starp brīdi, kad SCL signāls ir iestatīts uz 0, un datu izmaiņām SDA līnijā. Piešķirts ar parametru SDA_HV (SDA_Hold_Value) no tabulas datu pārraides ātruma reģistra ICR faktoram:

.

11.2.8.5. IICD datu reģistrs

MK sērijai AC, AW, Dx, EL, GB, GT, JM, LC, QE, QG, SG, SH, SL
Reģistrēties Režīms D7 D6 D5 D4 D3 D2 D1 D0
IICD Lasīšana I2C DATI
Ieraksts
Atiestatīt 0 0 0 0 0 0 0 0

Ja I2C modulis darbojas galvenajā režīmā, ierakstīšanas darbība šajā reģistrā uzsāk I2C komunikāciju (bet tikai tad, ja komunikācijas virziena bits IICC vadības reģistrā ir iestatīts pareizi, t.i., TX = 1). Pirmo baitu pēc sākuma stāvokļa, ko programma ieraksta datu reģistrā, vergi interpretē kā ierīces adresi. Tāpēc programmai ir pareizi jāveido pirmā baita saturs. Reģistra lasīšanas darbība atgriež pēdējo baitu, kas saņemts, izmantojot I2C. Reģistra nolasīšanas operācija iniciē arī nākamā baita saņemšanas sākumu, taču tikai tad, ja saziņas virziena bits IICC vadības reģistrā ir iestatīts pareizi, t.i. pie TX = 0! Ja TX = 1, reģistra nolasīšanas darbība neizraisīs jauna baita saņemšanu, izmantojot I2C no slave.

Ja I2C modulis darbojas pakārtotā režīmā, tad šajā reģistrā ierakstītie dati tiks pārsūtīti uz I2C kopnes SDA līniju, kad galvenā ierīce veiks saņemšanas ciklu no šī pakārtotā. Reģistra nolasīšanas operācija atgriež pēdējo baitu, kas saņemts no galvenā.

11.2.8.6. Kontroles reģistrs IICC2

MK sērijām AC, Dx, EL, JM, QE, SG, SH, SL
Reģistrēties Režīms D7 D6 D5 D4 D3 D2 D1 D0
IICC Lasīšana GCAEN ADEXT 0 0 0 AD10 AD9 AD8
Ieraksts
Atiestatīt 0 0 0 0 0 0 0 0

Pirmie soļi ar STM32 un mikroC kompilatoru ARM arhitektūrai — 4. daļa — I2C, pcf8574 un HD4478 balstīts LCD savienojums

Nākamo rakstu vēlos veltīt darbam ar kopējo i2c interfeisu, ko bieži izmanto dažādās mikroshēmās, kas savienotas ar mikrokontrolleru.

I2C ir kopne, kas darbojas, izmantojot divus fiziskus savienojumus (papildus kopējam vadam). Internetā par to ir rakstīts diezgan daudz, Vikipēdijā ir labi raksti. Turklāt kopnes darbības algoritms ir ļoti skaidri aprakstīts. Īsāk sakot, kopne ir divu vadu sinhronā kopne. Kopnē vienlaikus var būt līdz 127 ierīcēm (ierīces adrese ir 7 biti, pie tā atgriezīsimies vēlāk). Tālāk ir parādīta tipiska ierīču savienošanas shēma ar i2c kopni ar MK kā galveno ierīci.


Attiecībā uz i2c visas ierīces (gan galvenās, gan palīgierīces) izmanto atvērtās kanalizācijas izejas. Vienkārši sakot, tie var TIKAI piesaistīt riepu zemei. Augsto kopnes līmeni nodrošina uzvilkšanas rezistori. Šo rezistoru vērtību parasti izvēlas diapazonā no 4,7 līdz 10 kOhm. i2c ir diezgan jutīgs pret fiziskajām līnijām, kas savieno ierīces, tāpēc, ja tiek izmantots savienojums ar lielu kapacitāti (piemēram, garš plāns vai ekranēts kabelis), šīs kapacitātes ietekme var “izpludināt” signāla malas un traucēt normāla darbība riepas. Jo mazāks ir pievilkšanas rezistors, jo mazāka ir šī kapacitātes ietekme uz signāla malu raksturlielumiem, bet jo LIELĀKA SLODZE uz izejas tranzistoriem i2c saskarnēs. Šo rezistoru vērtība tiek izvēlēta katrai konkrētai ieviešanai, taču tie nedrīkst būt mazāki par 2,2 kOhms, pretējā gadījumā jūs varat vienkārši sadedzināt izejas tranzistorus ierīcēs, kas darbojas ar kopni.

Kopne sastāv no divām līnijām: SDA (datu līnija) un SCL (pulksteņa signāls). Pulksteņi kopnes Master ierīci, parasti mūsu MK. Ja SCL ir augsts, informācija tiek nolasīta no datu kopnes. SDA stāvokli var mainīt tikai tad, ja pulksteņa signāls ir zems.. Ja SCL ir augsts, SDA signāls mainās, ģenerējot signālus SĀKT (kad SCL ir augsts, SDA signāls mainās no augsta uz zemu) un STOP - ja SCL līmenis ir augsts, SDA signāls mainās no zema uz augstu).

Atsevišķi jāsaka, ka i2c adrese ir norādīta kā 7 bitu skaitlis. 8 - vismazāk nozīmīgais bits norāda datu pārraides virzienu 0 - nozīmē, ka vergs pārsūtīs datus, 1 - saņems.. Īsumā, algoritms darbam ar i2c ir šāds:

  • Augsts SDA un SCL līmenis- autobuss ir bezmaksas, var sākt strādāt
  • Master pacēlāji SCL uz 1 un maina stāvokli S.D.A. no 1 līdz 0 - piesaista to zemei ​​- veidojas signāls SĀKT
  • Vadītājs pārsūta 7 bitu pakārtotu adresi ar virziena bitu (dati par S.D.A. tiek izstādīti, kad SCL velk pie zemes un nolasa vergs, kad tas tiek atbrīvots). Ja vergam nav laika “paķert” iepriekšējo bitu, tas piesaista SCL pie zemes, liekot kapteinim saprast, ka datu kopnes stāvoklis nav jāmaina: "Es joprojām lasu iepriekšējo." Pēc tam, kad meistars ir atlaidis riepu, viņš pārbauda vai vergs viņu atlaida?.
  • Pēc 8 adreses bitu pārsūtīšanas galvenais ģenerē 9. pulksteņa ciklu un atbrīvo datu kopni. Ja vergs dzirdēja viņa adresi un pieņēma to, tad viņš nospiedīs S.D.A. uz zemi. Tādā veidā tiek veidots signāls JAUTĀT- pieņemts, viss kārtībā. Ja vergs neko nesaprot vai viņa vienkārši nav, tad nebūs neviena, kas nospiestu riepu. meistars gaidīs taimautu un sapratīs, ka nesaprata.
  • Pēc adreses pārsūtīšanas, ja esam uzstādījuši virzienu no saimnieka līdz vergam(8 adreses biti ir vienādi ar 1), tad kapteinis pārsūta datus uz vergu, neaizmirstot pārbaudīt JAUTĀT no palīgierīces, gaidot, kamēr pakārtotā ierīce apstrādās ienākošo informāciju.
  • Kad kapteinis saņem datus no vergu, pats galvenais ģenerē signālu JAUTĀT pēc katra baita saņemšanas, un vergs kontrolē tā klātbūtni. Meistars nedrīkst speciāli sūtīt JAUTĀT pirms komandas nosūtīšanas STOP, parasti vergam skaidri norādot, ka vairāk datu nav jāsniedz.
  • Ja pēc datu nosūtīšanas, ko veicis galvenais (rakstīšanas režīms), ir nepieciešams nolasīt datus no vergu, tad galvenais ģenerē signālu vēlreiz SĀKT , nosūtot vergu adresi ar lasīšanas karogu. (ja pirms komandas SĀKT netika pārsūtīts STOP tad tiek izveidota komanda RESTARTĒT). To izmanto, lai mainītu galvenā un pakārtotā saziņas virzienu. Piemēram, mēs nododam reģistra adresi vergam un pēc tam nolasām datus no tā.)
  • Pabeidzot darbu ar vergu, galvenais ģenerē signālu STOP- augstā pulksteņa signāla līmenī tas veido datu kopnes pāreju no 0 uz 1.
STM 32 ir ar aparatūru ieviesti i2c kopnes raiduztvērēji. MK šādi moduļi var būt 2 vai 3. To konfigurēšanai tiek izmantoti speciāli reģistri, kas aprakstīti izmantotā MK atsaucē.

Programmā MicroC pirms i2c (kā arī jebkuras perifērijas) lietošanas tas ir pareizi jāinicializē. Lai to izdarītu, mēs izmantojam šādu funkciju (inicializācija kā galvenais):

I2Cn_Init_Advanced(garš neparakstīts: I2C_ClockSpeed, const Module_Struct *modulis);

  • n- piemēram, izmantotā moduļa numurs I2C1 vai I2C2.
  • I2C_ClockSpeed- kopnes ātrums, 100000 (100 kbs, standarta režīms) vai 400000 (400 kbs, ātrais režīms). Otrais ir 4 reizes ātrāks, taču ne visas ierīces to atbalsta
  • * modulis- piemēram, rādītājs uz perifērijas moduli &_GPIO_MODULE_I2C1_PB67, neaizmirsīsim šeit to Koda palīgs (ctrl-space ) ļoti palīdz.
Vispirms pārbaudīsim, vai autobuss ir brīvs; tam ir funkcija I2Cn_Is_Idle(); atgriež 1, ja autobuss ir brīvs, un 0, ja tajā ir maiņa.

I2Cn_Start();
Kur n- mūsu mikrokontrollera izmantotā i2c moduļa numurs. Funkcija atgriezīs 0, ja kopnē ir kļūda, un 1, ja viss ir kārtībā.

Lai pārsūtītu datus uz vergu, mēs izmantojam funkciju:

I2Cn_Write(unsigned char slave_address, unsigned char *buf, unsigned long count, unsigned long END_mode);

  • n- izmantotā moduļa numurs
  • vergu_adrese- 7 bitu vergu adrese.
  • *buf- rādītājs uz mūsu datiem - baits vai baitu masīvs.
  • skaitīt- pārsūtīto datu baitu skaits.
  • END_režīms- ko darīt pēc datu pārsūtīšanas uz vergu, END_MODE_STOP - pārraidīt signālu STOP, vai END_MODE_RESTART sūtīt vēlreiz SĀKT, ģenerējot signālu RESTARTĒT un paskaidrojot nodaļai, ka sesija ar viņu nav beigusies un tagad no viņa tiks nolasīti dati.
Lai nolasītu datus no vergu, izmantojiet funkciju:

I2Cn_Read(char slave_address, char *ptrdata, unsigned long count, unsigned long END_mode);

  • n- izmantotā moduļa numurs
  • vergu_adrese- 7 bitu vergu adrese.
  • *buf- rādītājs uz mainīgo vai masīvu, kurā mēs saņemam datus, ierakstiet char vai short int
  • skaitīt- saņemto datu baitu skaits.
  • END_režīms- ko darīt pēc datu saņemšanas no verga - END_MODE_STOP - pārraidīt signālu STOP, vai END_MODE_RESTART nosūtīt signālu RESTARTĒT.
Mēģināsim kaut ko pieslēgt mūsu MK. Sākumā: plaši izplatītā PCF8574(A) mikroshēma, kas ir ieejas/izejas portu paplašinātājs, ko kontrolē, izmantojot i2c kopni. Šajā mikroshēmā ir tikai viens iekšējais reģistrs, kas ir tā fiziskais I/O ports. Tas ir, ja jūs nododat viņai baitu, tas nekavējoties tiks pakļauts viņas secinājumiem. Ja no tā skaita baitu (Transmit SĀKT adrese ar nolasīto karogu, signālu RESTERT, lasīt datus un visbeidzot ģenerēt signālu STOP), tad tā izvadēs atspoguļos loģiskos stāvokļus. Savienosim mūsu mikroshēmu saskaņā ar datu lapu:


Mikroshēmas adrese veidojas no tapu stāvokļa A0, A1, A2. Mikroshēmai PCF8574 adrese būs: 0100A0A1A2. (Piemēram, mums ir A0, A1, A2 augstā līmenī, tāpēc mūsu mikroshēmas adrese būs 0b0100 111 = 0x27). Priekš PCF8574A - 0111A0A1A2, kas ar mūsu savienojuma shēmu dos adresi 0b0111 111 = 0x3F. Ja, teiksim, A2 ir savienots ar zemi, tad adrese PCF8574A gribu 0x3B. Kopumā uz vienas i2c kopnes var vienlaicīgi uzstādīt 16 mikroshēmas, katrā pa 8 PCF8574A un PCF8574.

Mēģināsim kaut ko pārsūtīt, inicializēt i2c kopni un kaut ko pārsūtīt uz mūsu PCF8574.

#define PCF8574A_ADDR 0x3F //Mūsu PCF8574 adrese nav spēkā I2C_PCF8574_WriteReg(unsigned char wData) ( I2C1_Start(); // Ģenerējiet START signālu I2C1_Write un pārsūtiet datus no /PCF8574A_ADDR,&wDaEND; STOP signāls) char PCF8574A_reg ; // mainīgais, ko ierakstām laukā PCF8574 void main () ( I2C1_Init_Advanced(400000, &_GPIO_MODULE_I2C1_PB67); // Sākt I2C delay_ms(25); // Pagaidiet nedaudz PCF8574A_reg.b0 = 0 pirmā gaismas diode; //.8b7. = 1; // izslēdziet otro LED, kamēr (1) ( delay_ms(500); PCF8574A_reg.b0 = ~PCF8574A_reg.b0; PCF8574A_reg.b1 = ~PCF8574A_reg.b1; // invertējiet gaismas diožu stāvokli I2C_WFrite85A (4F_WFrite85A) ; // pārsūtīt datus uz mūsu PCF8574 ) )
Mēs apkopojam un palaižam savu programmu un redzam, ka mūsu gaismas diodes mirgo pārmaiņus.
Es pievienoju LED katodu mūsu PCF8574 kāda iemesla dēļ. Lieta tāda, ka, ja izejā tiek pievadīts loģiskais 0, mikroshēma godīgi novelk savu izeju uz zemi, bet, kad tiek pielikts loģiskais 1, tā savieno to ar + barošanu caur strāvas avotu 100 μA. Tas nozīmē, ka izejā nevar iegūt “godīgu” loģisko 1. Un jūs nevarat iedegt LED ar 100 µA. Tas tika darīts, lai konfigurētu PCF8574 izvadi uz ieeju bez papildu reģistriem. Mēs vienkārši rakstām uz izvades reģistru 1 (būtībā iestatot tapu stāvokļus uz Vdd) un varam to vienkārši saīsināt ar zemi. Strāvas avots neļaus mūsu I/O paplašinātāja izejas stadijai “izdegt”. Ja kāju pievelk pie zemes, tad uz tās ir zemes potenciāls, un tiek nolasīts loģiskais 0. Ja kāja tiek pievilkta līdz +, tad tiek nolasīts loģiskais 1. No vienas puses, tas ir vienkārši, bet no otras jums tas vienmēr jāatceras, strādājot ar šīm mikroshēmām.


Mēģināsim nolasīt mūsu paplašinātāja mikroshēmas tapu stāvokli.

#define PCF8574A_ADDR 0x3F //Mūsu PCF8574 adrese nav spēkā I2C_PCF8574_WriteReg(unsigned char wData) ( I2C1_Start(); // Ģenerēt START signālu I2C1_Write (PCF8574A_ADDR, &wDaEND datu pārsūtīšana un //1 byDE, &wDaEND); STOP signāls) void I2C_PCF8574_ReadReg (neparakstīta char rData) ( I2C1_Start(); // Ģenerējiet START signālu I2C1_Read(PCF8574A_ADDR, &rData, 1, END_MODE_STOP); // Lasiet 1 baitu datu 7) un ģenerējiet char STOP8 signālu. //mainīgais, ko rakstām uz PCF8574 char PCF8574A_out; // mainīgais, kurā lasām, un PCF8574 char lad_state; //mūsu gaismas diode ir ieslēgta vai izslēgta void main () ( I2C1_Init_Advanced(400000, &_GPIO_MODULE_I2C1_PB67); // Sākt I2C delay_ms(25); // Pagaidiet nedaudz PCF8574A_reg.b0 = 0; // iededziet pirmo LED LED = PCF8.5b7 1; / / izslēdziet otro LED PCF8574A_reg.b6 = 1; // Pavelciet kontaktus 6 un 7, lai ieslēgtu strāvu. PCF8574A_reg.b7 = 1; while (1) ( delay_ms(100); I2C_PCF8574_WriteReg (PCF8574A_reg); // rakstiet datus uz PCF8574 I2C_PCF8574_ReadReg (PCF8574 A_out ); // lasīt no PCF8574 if (~PCF8574A_out.b6) PCF8574A_reg.b0 = ~PCF8574A_reg.b0; // Ja tiek nospiests 1. bits no PCF 4, tad tiek nospiesta poga 5 by 6 no PCF. ieslēdziet/izslēdziet mūsu LED), ja (~PCF8574A_out .b7) PCF8574A_reg.b1 = ~PCF8574A_reg.b1; // līdzīgi 2 pogām un 2 gaismas diodēm ) )
Tagad, nospiežot pogas, mēs ieslēdzam vai izslēdzam mūsu LED. Mikroshēmai ir cita izeja INT. Uz tā tiek ģenerēts impulss katru reizi, kad mainās mūsu I/O paplašinātāja tapu stāvoklis. Savienojot to ar mūsu MK ārējo pārtraukumu ieeju (kā konfigurēt ārējos pārtraukumus un kā ar tiem strādāt, es jums pastāstīšu kādā no šiem rakstiem).

Izmantosim mūsu porta paplašinātāju, lai caur to savienotu rakstzīmju displeju. To ir ļoti daudz, taču gandrīz visi ir veidoti, pamatojoties uz kontroliera mikroshēmu HD44780 un viņa kloni. Piemēram, es izmantoju LCD2004 displeju.


Tā un kontroliera HD44780 datu lapu var viegli atrast internetā. Savienosim savu displeju ar PCF8574 un viņas displeju attiecīgi ar mūsu STM32.

HD44780 izmanto paralēlu interfeisu. Dati tiek pārraidīti ar 8 (vienā pulksteņa ciklā) vai 4 (2 pulksteņa ciklos) vārtu impulsiem izejā E. (nolasa displeja kontrolleris lejupejošā malā, pāreja no 1 uz 0). Secinājums R.S. norāda, vai mēs sūtām datus uz mūsu displeju ( RS = 1) (rakstzīmes, kurām tai vajadzētu parādīt, patiesībā ir ASCII kodi) vai komandu ( RS = 0). RW norāda datu pārsūtīšanas, rakstīšanas vai lasīšanas virzienu. Parasti mēs ierakstām datus displejā, tāpēc ( RW=0). Rezistors R6 kontrolē displeja kontrastu. Kontrasta regulēšanas ieeju nevar vienkārši savienot ar zemi vai strāvu, pretējā gadījumā jūs neko neredzēsit.. VT1 izmanto, lai ieslēgtu un izslēgtu displeja fona apgaismojumu saskaņā ar MK komandām. MicroC ir bibliotēka darbam ar šādiem displejiem, izmantojot paralēlo interfeisu, taču parasti ir dārgi pavadīt 8 kājas uz displeja, tāpēc es gandrīz vienmēr izmantoju PCF8574, lai strādātu ar šādiem ekrāniem. (Ja kādam ir interese, uzrakstīšu rakstu par darbu ar HD44780 bāzes displejiem, kas iebūvēti MicroC caur paralēlo interfeisu.) Apmaiņas protokols nav īpaši sarežģīts (izmantosim 4 datu līnijas un pārsūtīsim informāciju 2 pulksteņa ciklos), to skaidri parāda šāda laika diagramma:


Pirms datu pārsūtīšanas uz mūsu displeju tie ir jāinicializē, nododot servisa komandas. (aprakstīts datu lapā, šeit mēs piedāvājam tikai visbiežāk lietotos)

  • 0x28- saziņa ar indikatoru, izmantojot 4 līnijas
  • 0x0C- iespējot attēla izvadi, atspējot kursora displeju
  • 0x0E- iespējot attēla izvadi, iespējot kursora displeju
  • 0x01- notīriet indikatoru
  • 0x08- atspējot attēla izvadi
  • 0x06- pēc simbola parādīšanas kursors pārvietojas par 1 pazīstamu vietu
Tā kā ar šo indikatoru mums būs jāstrādā diezgan bieži, mēs izveidosim spraudņu bibliotēku "i2c_lcd.h" . Lai to izdarītu iekšā Projektu menedžeris Galvenes faili un izvēlēties Pievienot jaunu failu . Izveidosim mūsu galvenes failu.

#define PCF8574A_ADDR 0x3F //Mūsu PCF8574 adrese #define DB4 b4 // Atbilstība starp PCF8574 tapām un indikatoru #define DB5 b5 #define DB6 b6 #define DB7 b7 #define EN b3 #define RW b1 BL b0 // fona apgaismojuma vadība #define dislenth 20 // rakstzīmju skaits mūsu displeja rindā static unsigned char BL_status; // mainīgais, kas saglabā fona apgaismojuma stāvokli (ieslēgts/izslēgts) void lcd_I2C_Init(void); // Displeja un PCF8574 inicializācijas funkcija void lcd_I2C_txt(char *pnt); // Parāda teksta rindiņu, parametrs ir rādītājs uz šo rindiņu void lcd_I2C_int(int pnt); // Parāda vesela skaitļa mainīgā vērtību, parametrs ir izvades vērtība void lcd_I2C_Goto(unsigned short row, unsigned short col); // pārvieto kursoru uz norādīto pozīciju, parametru rinda - rinda (no 1 līdz 2 vai 4 atkarībā no displeja) un kolonna - (no 1 līdz dislenth)) void lcd_I2C_cls(); // Notīra ekrāna tukšumu lcd_I2C_backlight (neparakstīts īss int stāvoklis); // Iespējo (raidot 1 un atspējo - pārraidot 0, displeja fona apgaismojumu)
Tagad aprakstīsim savas funkcijas, atkal pārejam pie Projektu menedžeris ar peles labo pogu noklikšķiniet uz mapes Avoti un izvēlēties Pievienot jaunu failu . Izveidojiet failu "i2c_lcd.c" .

#include "i2c_lcd.h" //iekļaut mūsu galvenes failu char lcd_reg; //pagaidu uzglabāšanas reģistrs datiem, kas nosūtīti uz PCF8574 void I2C_PCF8574_WriteReg(unsigned char wData) //funkcija datu nosūtīšanai caur i2c uz PCF8574 mikroshēmu ( I2C1_Start(); I2C1_Write(PCF8574A_ADDR,&wDaCOM) (LCF8574A_ADDR,&wDaCOM); com) //funkcija komandas nosūtīšanai uz mūsu displeju ( lcd_reg = 0; //ierakstīt 0 pagaidu reģistrā lcd_reg.BL = BL_status.b0; //iestatiet fona apgaismojuma tapu atbilstoši fona apgaismojuma saglabāšanas mainīgā vērtībai stāvoklis lcd_reg.DB4 = com.b4; // iestatiet mūsu komandas 4 nozīmīgākos bitus uz indikatora datu kopni lcd_reg.DB5 = com.b5; lcd_reg.DB6 = com.b6; lcd_reg.DB7 = com.b7; lcd_reg .EN = 1; //iestatiet stroboskopa izvadi uz 1 I2C_PCF8574_WriteReg ( lcd_reg); //rakstiet PCF8574 reģistrā, faktiski nosūtot datus indikatoram delay_us (300); //gaidiet taimautu lcd_reg.EN = 0; // atiestatiet stroboskopa impulsu uz 0, indikators nolasa datus I2C_PCF8574_WriteReg (lcd_reg); delay_us (300) ; lcd_reg = 0; lcd_reg.BL = BL_status.b0; lcd_reg.DB4 = com.b0; //s vismazāk nozīmīga biti lcd_reg.DB5 = com.b1; lcd_reg.DB6 = com.b2; lcd_reg.DB7 = com.b3; lcd_reg.EN = 1; I2C_PCF8574_WriteReg(lcd_reg); delay_us(300); lcd_reg.EN = 0; I2C_PCF8574_WriteReg(lcd_reg); delay_us(300); ) spēkā neesošs LCD_CHAR (unsigned char com) //nosūta datus (ASCII rakstzīmju kods) indikatoram ( lcd_reg = 0; lcd_reg.BL = BL_status.b0; lcd_reg.EN = 1; lcd_reg.RS = 1; //rakstzīmes nosūtīšana atšķiras no komandu nosūtīšanas, iestatot RS bitu uz 1 lcd_reg.DB4 = com.b4; //iestata 4 nozīmīgākos bitus ieejās lcd_reg.DB5 = com.b5; lcd_reg.DB6 = com.b6; lcd_reg.DB7 = com.b7; I2C_PCF8574_WriteReg (lcd_reg) ; delay_us (300); lcd_reg.EN = 0; // atiestatiet stroboskopa impulsu uz 0, indikators nolasa datus I2C_PCF8574_WriteReg (lcd_reg); delay_us;0reg_l (c3d_reg); .BL = BL_status.b0; lcd_reg.EN = 1; lcd_reg.RS = 1; lcd_reg.DB4 = com.b0; //iestatiet 4 vismazāk nozīmīgos bitus ieejās lcd_reg.DB5 = com.b1; lcd_reg.DB6 = lv vanced(400000, &_GPIO_MODULE_I2C1_PB67 ); //inicializējiet mūsu I2c moduli M K delay_ms(200) ; lcd_Command(0x28); // Displejs ar 4 bitiem pulksten režīmā delay_ms (5); lcd_Command(0x08); //Atspējot datu izvadi uz displeju delay_ms (5); lcd_Command(0x01); //Notīrīt displeju delay_ms (5); lcd_Command(0x06); //Iespējot automātisko kursora nobīdi pēc simbola delay_ms parādīšanas (5); lcd_Command(0x0C); //Ieslēgt informācijas attēlošanu, neparādot kursoru delay_ms (25); ) void lcd_I2C_txt(char *pnt) //Izvadīt displejā rakstzīmju virkni ( unsigned short int i; //pagaidu rakstzīmju masīva indeksa mainīgais char tmp_str; //pagaidu rakstzīmju masīvs, garums 1 ir lielāks par displeja garumu rindiņa, jo rinda ir jāpabeidz сiv ar NULL ASCII rakstzīmi 0x00 strncpy(tmp_str, pnt, dislenth); //iekopējiet ne vairāk kā oriģinālās virknes izkliedētās rakstzīmes mūsu pagaidu virknē (i=0; i Tagad savienosim jaunizveidoto bibliotēku ar failu ar mūsu galveno funkciju:

#include "i2c_lcd.h" //iekļaut mūsu galvenes failu unsigned int i; //pagaidu mainīgo skaitītājs void main() (lcd_I2C_Init(); //inicializēt displeju lcd_I2C_backlight (1); //ieslēdziet fona apgaismojumu lcd_I2C_txt ("Sveiki, habrahabr"); //parādīt rindiņu, kamēr (1) ( delay_ms() 1000) ; lcd_I2C_Goto (2,1); //pāriet uz 2. rindiņas 1. rakstzīmi lcd_i2c_int (i); //parādīt vērtību i++; //palielināt skaitītāju ) )

Ja viss ir pareizi salikts, indikatorā vajadzētu redzēt tekstu un skaitītāju, kas palielinās katru sekundi. Vispār nekas sarežģīts :)

Nākamajā rakstā mēs turpināsim izprast i2c protokolu un ierīces, kas ar to darbojas. Apsvērsim iespēju strādāt ar EEPROM 24XX atmiņu un MPU6050 akselerometru/žiroskopu.

Šodien uz mūsu operāciju galda ir jauns viesis, tas ir Microchip produkts, MCP23008-E porta paplašinātājs. Šī lieta ir paredzēta (kā norāda nosaukums), lai palielinātu mikrokontrollera I/O kāju skaitu, ja tās pēkšņi kļūst nepietiekamas. Protams, ja mums vajag kājas un izejas, tad varam ņemt un par to neuztraukties. Ja jums ir nepieciešamas ievades kājas, tad ir risinājums, kas balstīts uz stingru loģiku. Ja mums ir vajadzīgas gan ieejas, gan izejas un arī kontrolēta ieeju pievilkšana, tad portu paplašinātājs, iespējams, ir normālākais risinājums. Kas attiecas uz ierīces cenu, tad tā ir ļoti pieticīga – apmēram buks. Šajā rakstā es mēģināšu detalizēti aprakstīt, kā vadīt šo mikroshēmu, izmantojot AVR mikrokontrolleri.

Pirmkārt, nedaudz par īpašībām:

  • 8 neatkarīgas porta tapas
  • Interfeiss saziņai ar ārpasauli - I2C (frekvence līdz 1,7 MHz)
  • Pielāgojama pievilkšanās ieejām
  • Var raustīt kāju, kad mainās noteiktas ievades stāvoklis
  • Trīs ieejas mikroshēmas adreses iestatīšanai (vienā kopnē varat piekārt 8 ierīces)
  • Darba spriegums no 1,8 līdz 5,5 voltiem
  • Zems strāvas patēriņš
  • Liela korpusu izvēle (PDIP/SOIC/SSOP/QFN)

Man labāk patīk I2C interfeiss, tas mani piesaista ar nelielu vadu skaitu :-) tomēr, ja jums ir nepieciešams ļoti ātrs ātrums (līdz 10 MHz), tad jums ir jāizmanto SPI interfeiss, kas atrodas MCP23S08. Atšķirība starp MCP23S08 un MCP23008, kā es saprotu, ir tikai saskarnē un mikroshēmas adreses iestatīšanas kāju skaitā. Kuram patīk kaut kas īsāks? Mikruhi spraudnis ir datu lapā, tas nekādā veidā nav interesants un šeit netiks ņemts vērā. Tāpēc nekavējoties pāriesim pie tā, kā sākt strādāt ar šo ierīci. Viss darbs ir saistīts ar noteiktu datu rakstīšanu un nolasīšanu no mikroshēmas reģistriem. Man par prieku, reģistru nemaz nebija daudz - tikai vienpadsmit. Datu rakstīšana un lasīšana no reģistriem ir ļoti vienkārša, ierakstiet par to. Tiesa, mēs nerunājam par reģistriem, bet princips ir vienāds. Tagad atliek tikai izdomāt, no kuriem reģistriem ko lasīt un kuros reģistros ko rakstīt. Protams, datu lapa mums to palīdzēs. No datu lapas mēs uzzinām, ka mikroshēmai ir šādi reģistri:

IODIR reģistrs
Norāda datu plūsmas virzienu. Ja noteiktai kājai atbilstošais bits ir iestatīts uz vienu, tad kājiņa ir ievade. Ja atiestatīts uz nulli, izejiet. Īsāk sakot, šis reģistrs ir analogs DDRx AVR (tikai AVR 1 ir izeja un 0 ir ieeja).

IPOL reģistrs
Ja ir iestatīts reģistra bits, attiecīgajai daļai tiek iespējota ievades inversija. Tas nozīmē, ka, ja jūs uzklājat baļķi uz kājas. nulle, tad no GPIO reģistra tiek uzskatīts par vienu un otrādi. Šīs funkcijas lietderība ir ļoti apšaubāma.

GPINTEN reģistrs
Katrs šī reģistra bits atbilst noteiktai porta tapai. Ja bits ir iestatīts, attiecīgā porta tapa, kas konfigurēta kā ieeja, var izraisīt pārtraukumu. Ja bits ir atiestatīts, neatkarīgi no tā, ko jūs darāt ar porta kāju, pārtraukums nebūs. Pārtraukšanas nosacījumus nosaka šādi divi reģistri.

DEFVAL reģistrs
Ievadei konfigurēto tapu pašreizējā vērtība tiek pastāvīgi salīdzināta ar šo reģistru. Ja pēkšņi pašreizējā vērtība sāk atšķirties no šajā reģistrā esošās, tad notiek pārtraukums. Vienkārši sakot, ja bits ir iestatīts, pārtraukums notiks, kad līmenis mainās no augsta uz zemu attiecīgajā daļā. Ja bits tiek atiestatīts, pārtraukums notiek augošā malā.

INTCON reģistrs
Katrs šī reģistra bits atbilst noteiktai porta tapai. Ja bits ir skaidrs, tad jebkura loģiskā līmeņa maiņa uz pretējo izraisa pārtraukumu. Ja bits ir iestatīts, pārtraukuma rašanos ietekmē DEFVAL reģistrs (pretējā gadījumā tas tiek pilnībā ignorēts).

IOCON reģistrs
Šis ir iestatījumu reģistrs. Tas sastāv no četriem bitiem:
SEQOP— bits kontrolē adreses automātisko palielināšanu. Ja tas ir instalēts, automātiskā palielināšana ir atspējota, pretējā gadījumā tā ir iespējota. Ja mēs to izslēdzam, mēs varam ļoti ātri nolasīt viena un tā paša reģistra vērtību, jo mums nav katru reizi jāpārraida tā adrese. Ja jums ir nepieciešams ātri nolasīt visus 11 reģistrus pēc kārtas, tad ir jāiespējo automātiskā palielināšana. Katru reizi, kad no reģistra tiek nolasīts baits, pati adrese palielināsies par vienu, un tā nebūs jāpārraida.
DISSLW— Kas zina, kas tas ir. Neatkarīgi no tā, kā es to griežu, viss joprojām darbojas. Priecāšos, ja kāds paskaidros.
HAEN— INT izejas iestatīšanas bits. Ja tas ir iestatīts, tapa tiek konfigurēta kā atvērta aizplūšana, ja bits ir atiestatīts, tad aktīvais līmenis uz INT kājas nosaka INTPOL bitu
INTPOL— nosaka aktīvo līmeni uz INT kājas. Ja tas ir iestatīts, aktīvais līmenis ir viens, pretējā gadījumā nulle.

Vēl ir mazliet HAEN bet tas netiek izmantots šajā mikroshēmā (ieslēdz/izslēdz aparatūras adresācijas tapas MCP23S08)

GPPU reģistrs
Kontrolē ievades vilkšanu. Ja bits ir iestatīts, uz atbilstošās tapas parādīsies pievilkšanās uz barošanas avotu caur 100 kOhm rezistoru.

INTF reģistrs
Pārtraukt karogu reģistru. Ja bits ir iestatīts, tas nozīmē, ka attiecīgais porta posms izraisīja pārtraukumu. Protams, GPINTEN reģistrā ir jāiespējo pārtraukumi nepieciešamajām daļām

INTCAP reģistrs
Kad notiek pārtraukums, viss ports tiek nolasīts šajā reģistrā. Ja pēc tam ir vairāk pārtraukumu, šī reģistra saturs netiks pārrakstīts ar jauno vērtību, līdz mēs to izlasīsim vai GPIO.

GPIO reģistrs
Nolasot datus no reģistra, mēs nolasām loģiskos līmeņus uz porta tapām. Ierakstot datus, mēs uzstādām loģiskos līmeņus. Rakstot uz šo reģistru, tie paši dati automātiski tiek ierakstīti OLAT reģistrā

OLAT reģistrs
Ierakstot datus šajā reģistrā, mēs izvadām datus uz portu. Ja jūs nolasīsit datus no turienes, jūs nolasīsit to, kas tika pierakstīts, nevis to, kas patiesībā atrodas porta ieejās. Lai lasītu ievades, mēs izmantojam tikai GPIO.

Manuprāt, reģistru apraksts ir diezgan normāls, un tas nevienu nedrīkstētu sagraut. Tagad sava prieka pēc uzrakstīsim nelielu demonstrāciju, kurā tiks aptaujātas 4 pogas, kas savienotas ar porta paplašinātāju, un atkarībā no to stāvokļa iedegsies vai izslēgs 4 atbilstošas ​​gaismas diodes, kas savienotas ar to pašu paplašinātāju. Piemērs būs pēc iespējas vienkāršāks, bez pārtraukumiem. Mēs vienkārši pastāvīgi lasām pogu stāvokli un parādām šo stāvokli uz gaismas diodēm. Mūsu ierīces shēma izskatīsies šādi:

Pārtraukšanas tapai nav jābūt savienotai, mums tas šeit nav vajadzīgs, taču ir nepieciešama atiestatīšanas kājas pievilkšanās! Es pavadīju daudz laika, līdz sapratu, ka mans porta paplašinātājs periodiski tiek atiestatīts pievilkšanas trūkuma dēļ. Tagad ķersimies pie koda. Protams, mēs rakstīsim tālāk. Vienkāršs kods:

Programma rashiritel; const AdrR=%01000001; //Chēmas adrese ar lasīšanas bitu const AdrW=%01000000; //Chēmas adrese ar bitu ierakstu var r:byte; ///Procedūra ieraksta datus no Dat mainīgā uz reģistru pēc adreses Adr Procedure WriteReg(Dat,Adr:byte); Sākt TWI_Start(); TWI_Write(AdrW); TWI_Write(Adr); TWI_Write(Dat); TWI_Stop(); Beigas; ///Funkcija atgriež reģistra vērtību adresē Adr Funkcija ReadReg(Adr:byte):byte; var a:baits; Sākt TWI_Start(); TWI_Write(AdrW); TWI_Write(Adr); TWI_Start(); TWI_Write(AdrR); a:=TWI_Lasīt(0); TWI_Stop(); rezultāts:=a; Beigas; sākt TWI_INIT(200000); ///Inicializē i2c WriteReg(%00001111,0x00); //Zemākie 4 biti ir ieejas, bet atlikušie 4 biti ir izejas WriteReg(%00001111,0x06); //Ieslēgts uzvilkšana 4 ievadiem Kamēr TRUE do Begin r:=ReadReg(0x09); //Nolasīt ievades stāvokli r:= NOT r; //Ir nepieciešams apgriezt bitus, pretējā gadījumā, atlaižot pogu, iedegsies gaismas diodes r:= r shl 4; //Shift 4 biti pa kreisi... WriteReg(r,0x0A); //Parādīt pogu beigu stāvokli; beigas.

Publicēts 26.10.2016

Iepriekšējā rakstā mēs apskatījām STM32 darbību ar I 2 C kopni kā Master. Tas ir, viņš bija vadītājs un nopratināja sensoru. Tagad padarīsim STM32 par vergu un atbildēsim uz pieprasījumiem, tas ir, tas pats darbojas kā sensors. Reģistriem ar adresēm no 0 līdz 0xFF atvēlēsim 255 baitus atmiņas un ļausim Meistaram tos rakstīt/lasīt. Un, lai piemērs nebūtu tik vienkāršs, padarīsim mūsu STM32 par analogo-digitālo pārveidotāju ar I 2 C interfeisu. ADC apstrādās 8 kanālus. Pārveidojumu rezultātus kontrolieris dos Meistaram, lasot no reģistriem. Tā kā ADC konversijas rezultāts ir 12 biti, katram ADC kanālam ir nepieciešami 2 reģistri (2 baiti).

i2c_slave.h satur iestatījumus:

I2CSLAVE_ADDR– mūsu ierīces adrese;

ADC_ADDR_START– to reģistru sākuma adrese, kuri ir atbildīgi par ADC pārveidošanas rezultātiem.

Failā i2c_slave.c mūs visvairāk interesē funkcijas get_i2c1_ram Un set_i2c1_ram. Funkcija get_i2c1_ram ir atbildīgs par datu nolasīšanu no reģistriem. Tas atgriež datus no norādītās adreses, kas tiek dota Meistaram. Mūsu gadījumā dati tiek nolasīti no masīva i2c1_ram, bet, ja Master pieprasa reģistru adreses no diapazona, kas piešķirts ADC rezultātiem, tad tiek nosūtīti ADC konversijas dati.

get_i2c1_ram:

Uint8_t get_i2c1_ram(uint8_t adr) ( //ADC dati if ((ADC_ADDR_START<= adr) & (adr < ADC_ADDR_START + ADC_CHANNELS*2)) { return ADCBuffer; } else { // Other addresses return i2c1_ram; } }

Funkcija set_i2c1_ram– ieraksta no Meistara saņemtos datus reģistros ar norādīto adresi. Mūsu gadījumā dati tiek vienkārši ierakstīti masīvā i2c1_ram. Bet tas nav obligāti. Varat, piemēram, pievienot čeku un, kad noteiktā adresē pienāk noteikts numurs, veikt dažas darbības. Tādā veidā jūs varat nosūtīt dažādas komandas uz mikrokontrolleru.

set_i2c1_ram:

Void set_i2c1_ram(uint8_t adr, uint8_t val) ( i2c1_ram = val; return; )

Inicializācija ir diezgan vienkārša:

Int main(void) ( SetSysClockTo72(); ADC_DMA_init(); I2C1_Slave_init(); while(1) ( ) )

Vispirms iestatām kontroliera maksimālo darbības frekvenci. Maksimālais ātrums ir nepieciešams, ja ir jāizvairās no jebkādiem kavējumiem I 2 C kopnē. Tad mēs sākam ADC darbību, izmantojot DMA. PAR . PAR . Un visbeidzot mēs inicializējam I 2 C autobusu kā Vergs. Kā redzat, nekas sarežģīts.

Tagad savienosim mūsu STM32 moduli ar Raspberry Pi. Savienosim potenciometrus ar ADC kanāliem. Un mēs nolasīsim ADC indikatorus no mūsu kontroliera. Neaizmirstiet, ka, lai I 2 C kopne darbotos, katrā kopnes līnijā ir jāinstalē pievilkšanas rezistori.

Raspberry konsolē pārbaudīsim, vai mūsu ierīce ir redzama I 2 C kopnē (apmēram):

I2cdetect -y 1

Kā redzat, ierīces adrese 0x27, lai gan mēs norādījām 0x4E. Kad jums ir laiks, padomājiet par to, kāpēc tas notika.

Lai nolasītu no I 2 C-Slave ierīces reģistriem, izpildiet komandu:

I2cget -y 1 0x27 0x00

Kur:
0x27- ierīces adrese,
0x00– reģistra adrese (0x00…0xFF).

Lai rakstītu I 2 C-Slave ierīces reģistros, izpildiet komandu:

I2cset -y 1 0x27 0xA0 0xDD

De:
0x27- ierīces adrese,
0xA0- reģistrācijas adrese
0xDD-8 bitu dati (0x00…0xFF)

Iepriekšējā komanda reģistrā ierakstīja numuru 0xDD 0xA0(var rakstīt uz pirmajiem 16 reģistriem, bet nav jēgas, bet tie ir rezervēti ADC). Tagad lasīsim:

I2cget -y 1 0x27 0xA0

Lai vienkāršotu ADC kanāla datu nolasīšanas procesu, es uzrakstīju skriptu:

#!/usr/bin/env python import smbus importēšanas laiks kopne = smbus.SMBus(1) adrese = 0x27, kamēr (1): ADC = (); i diapazonā (0, 8): LBS = kopne.lasīšanas_baitu_dati(adrese, 0x00+i*2) MBS = kopne.lasīšanas_baita_dati(adrese, 0x00+i*2+1) ADC[i] = MBS*256 + LBS drukāt ADC time.sleep (0.2)

Tas aptauj un parāda visu 8 ADC kanālu rezultātus konsolei.

Līdzīgā veidā jūs varat apvienot vairākus mikrokontrollerus. Vienam no tiem jābūt Master(), otrai Slave.

Es novēlu jums panākumus!




Tops