STM32, kiolesura cha mfululizo cha I2C. STM32, kiolesura cha mfululizo I2C Stm32 i2c huashiria ack na nack

  • 18.03.2024

Hivi majuzi nimekuwa nikikutana na hakiki hasi kuhusu tairi. I2C katika STM32, wanasema kufanya kazi naye kunamaanisha kucheza na tari, nk.
Katika mwezi uliopita, niliweza kuzindua microcircuits mbili zinazoendelea I2C na hakuna dansi, usomaji mzuri wa hifadhidata.

Moduli I2C katika STM32 ina sifa zifuatazo:

  • inaweza kufanya kazi kwa njia mbili Fm(mode ya haraka) na Sm(hali ya kawaida), ya kwanza hufanya kazi kwa masafa hadi 400KHz, ya pili hadi 100KHz
  • Baiti 1 iliyo na usaidizi DMA
  • inasaidia hesabu ya hundi ya maunzi
  • kwa misingi yake inawezekana kutekeleza SMBus(Basi la Usimamizi wa Mfumo) na PMBus(Basi la Usimamizi wa Nguvu)
  • vekta mbili za kukatiza, zinazozalishwa wakati maambukizi yanafanikiwa na wakati kosa linatokea
  • kichujio cha kelele
  • inaweza kufanya kazi katika hali ya Mwalimu au Mtumwa
Katika hali kuu:
  • hutoa ishara ya wakati
  • inazalisha START na STOP
Katika hali ya utumwa:
  • unaweza kupanga anwani kuu na mbadala ambayo itajibu
  • inafafanua STOP

Kwa chaguo-msingi moduli iko katika hali Mtumwa, lakini inabadilika kiotomatiki hadi modi Mwalimu baada ya kizazi cha serikali ANZA.
Tofauti ya kimsingi kati ya Mwalimu na Mtumwa ni hiyo Mwalimu huzalisha mawimbi ya saa na daima huanzisha na kutamatisha uhamishaji wa data. Mtumwa sawa, hujibu anwani na matangazo yake, na majibu kwa anwani ya utangazaji yanaweza kuzimwa. Pia Mtumwa inazalisha serikali ACK, lakini pia inaweza kulemazwa.

Maelezo kama haya ya kina ni muhimu kwa sababu katika hali zote mbili kifaa kinaweza kufanya kama kisambazaji na kipokeaji.

  • Kisambazaji cha watumwa
  • Mpokeaji wa watumwa
  • Kisambazaji kikuu
  • Mpokeaji mkuu

Muundo wa moduli ya I2C umeonyeshwa hapa chini.

Dhibiti rejista I2C_CR1:

SWRST(Rudisha programu) - kitengo katika kidogo hiki kinaweka upya thamani ya rejista zote za moduli kwa hali ya msingi inaweza kutumika kuweka upya wakati kosa linatokea.

TAHADHARI(Tahadhari ya SBus) - kuweka kidogo hii kwa moja inaruhusu ishara kuzalishwa tahadhari katika hali SMBus.

PEC(Kuangalia makosa ya pakiti) - biti hii inadhibitiwa na programu, lakini inaweza kuwekwa upya na maunzi wakati PEC, START, STOP au PE=0 inapopitishwa. Moja katika biti hii huwezesha upitishaji CRC.

POS(Acknowledge/PEC Position (kwa mapokezi ya data)) - hali ya biti hii huamua nafasi ACK/PEC katika usanidi wa baiti mbili katika hali ya Mwalimu.

ACK(Acknowledge wezesha) - kitengo katika biti hii inaruhusu kutuma ACK/UCHUFU baada ya kupokea anwani au data byte.

SIMAMA(Acha kizazi) - kuweka kidogo hii kwa moja hutoa ishara SIMAMA katika hali ya Mwalimu.

ANZA(Anza kizazi) - kuweka kidogo hii kwa moja hutoa hali ANZA katika hali ya Mwalimu,

PUNGUA(Zimaza kunyoosha saa (Njia ya Mtumwa)) - ikiwa usindikaji wa data unachukua muda Mtumwa inaweza kusimamisha upitishaji mkuu kwa kushinikiza mstari SCL kwa ardhi, Mwalimu atasubiri na hatatuma chochote hadi mstari utakapotolewa. Sufuri katika mashinikizo kidogo hii SCL chini.

ENGC(Washa simu ya jumla) - ikiwa biti hii imewekwa kwa moja, moduli hujibu ACK om kutangaza anwani 0x00.

ENPEC(PEC wezesha) - kuweka kidogo hii kwa moja kuwezesha kuhesabu maunzi CRC.

ENARP(ARP wezesha) - kuweka kidogo hii kwa moja kuwezesha ARP.

SMBTYPE(Aina ya SBus) - ikiwa kidogo hii imewekwa kwa sifuri, moduli inafanya kazi katika hali ya Mtumwa, ikiwa moja iko katika hali ya Mwalimu.

SMBUS(Modi ya SBus) - ikiwa kidogo hii imewekwa kwa sifuri, moduli inafanya kazi ndani I2C, ikiwa moja SMBus.

P.E.(Uwezeshaji wa pembeni) - kitengo katika biti hii huwezesha moduli.

Dhibiti rejista I2C_CR2:

MWISHO(DMA ya mwisho uhamisho) - moja katika kidogo hii inaruhusu DMA toa ishara ya mwisho ya uwasilishaji EOT(Mwisho wa Uhamisho).

DMAEN(Maombi ya DMA yanawezesha) - kitengo katika sehemu hii inaruhusu kufanya ombi DMA wakati wa kuweka bendera TxE au RxNE.

ITBUFEN(Kukatiza kwa buffer kuwasha) - ikiwa biti hii ni wazi, ukatizaji wote umewezeshwa isipokuwa kwa kukatizwa kwa kupokea na kusambaza.

ITEVTEN(Washa usumbufu wa tukio) - moja katika biti hii huwezesha kukatizwa kwa tukio.

ITERREN(Kukatiza kwa hitilafu wezesha) - moja katika biti hii huwezesha kukatizwa makosa yanapotokea.

FREQ(Mzunguko wa saa ya pembeni) - frequency ya saa ya moduli lazima iandikwe kwenye uwanja huu kidogo inaweza kuchukua thamani kutoka 2 hadi 50.

Sajili I2C_OAR1:

ADDMODE(Njia ya kushughulikia) - kidogo hii huamua ukubwa wa anwani ya Mtumwa, sifuri inalingana na ukubwa wa anwani ya bits 7, moja - 10 bits.

ONGEZA(Anwani ya kiolesura) - sehemu muhimu zaidi za anwani, ikiwa anwani ni 10-bit.

ONGEZA(Anwani ya kiolesura) - anwani ya kifaa.

ADD0(Anwani ya kiolesura) - sehemu ndogo kabisa ya anwani, ikiwa anwani ni 10-bit..

Sajili I2C_OAR2:

ADD2- anwani mbadala ambayo Mtumwa atajibu.

MWISHO(Njia ya kuhutubia mara mbili wezesha) - moja katika biti hii inaruhusu Mtumwa kujibu anwani mbadala katika hali ya 7-bit.

I2C_DR- rejista ya data, kutuma data tunaandika kwenye rejista D.R., kwa mapokezi tunaisoma.

Rejesta ya hali ya I2C_SR1:

SMALERT(Tahadhari ya SBus) - hutokea katika kesi ya tahadhari kwenye basi SMBus.

MUDA UMEISHA(Timeout au Tlow error) - hutokea ikiwa mstari SCL kushinikizwa chini. Kwa bwana 10ms, kwa mtumwa 25mS.

PECERR(Hitilafu ya PEC katika mapokezi) - hutokea wakati kuna kosa PEC baada ya kuingia.

OVR(Overrun/Underrun) - hutokea wakati data inapita.

A.F.(Kukiri kushindwa) - kuweka wakati ishara inapokelewa UCHUFU. Ili kuweka upya, unahitaji kuandika 0.

ARLO(Usuluhishi uliopotea (hali ya bwana)) - kuweka wakati usuluhishi unapotea. Ili kuweka upya, unahitaji kuandika 0.

BER(Hitilafu ya basi) - hitilafu ya basi. Weka wakati ishara inatokea ANZA au SIMAMA kwa wakati mbaya.

TxE(Data rejista tupu (wasambazaji)) - kuweka wakati rejista ya DR haina tupu, au tuseme wakati data kutoka kwake imehamishwa kwenye rejista ya mabadiliko.

RxNE(Data rejista sio tupu (wapokeaji)) - kuweka wakati wa kupokea byte ya data isipokuwa anwani.

STOPF(Acha kugundua (hali ya mtumwa)) - wakati wa kufanya kazi ndani mtumwa kuweka wakati ishara imegunduliwa SIMAMA, ikiwa kulikuwa na ishara ya ACK hapo awali. Ili kuweka upya lazima usome SR1 na rekodi ndani CR1.

ADD10(Kichwa cha 10-bit kimetumwa (Njia kuu)) - kuweka wakati wa kutuma byte ya kwanza ya anwani ya 10-bit.

BTF(Uhamisho wa Byte umekamilika) - bendera imewekwa wakati byte inapokelewa / kupitishwa inafanya kazi tu wakati PUNGUA sawa na sifuri.

ADDR(Anwani imetumwa (hali ya bwana) / inafanana (hali ya mtumwa)) - katika hali bwana kuweka baada ya uhamisho wa anwani, katika hali mtumwa huwekwa wakati anwani inalingana. Ili kuweka upya, unahitaji kusoma sajili SR1 na kisha SR2.

S.B.(Anza kidogo (Njia kuu)) - weka wakati ishara ya START inatokea. Ili kuweka upya bendera lazima usome SR1 na uandike data kwenye rejista D.R. .

Rejesta ya hali ya I2C_SR2:

PEC(Daftari ya kuangalia makosa ya pakiti) - ukaguzi wa sura umeandikwa kwa uwanja huu kidogo.

DUALF(Bendera mbili (Njia ya Mtumwa)) - sifuri katika sehemu hii inaonyesha kuwa anwani ambayo Slave alipokea inalingana OAR1, vinginevyo OAR2.

SMBHOST(Kichwa cha mwenyeji wa SBus (Njia ya Mtumwa)) - weka wakati kichwa kinapokelewa Mpangishi wa SMBus.

SMBDEFAULT(Anwani ya chaguo-msingi ya kifaa cha SBus (Njia ya mtumwa)) - weka ikiwa anwani ya kawaida inakubaliwa
Kwa SMBus-vifaa.

GENCALL(Anwani ya simu ya jumla (Njia ya mtumwa)) - weka ikiwa anwani ya utangazaji inapokelewa katika hali ya mtumwa.

TRA(Transmitter/receiver) - moja katika biti hii inaonyesha kuwa moduli inafanya kazi kama kisambazaji, vinginevyo mpokeaji.

BUSY(Bus busy) - bendera yenye shughuli nyingi.

MSL(Mwalimu/mtumwa) - moja katika kidogo hii inaonyesha kwamba moduli inafanya kazi katika hali ya Mwalimu, vinginevyo Mtumwa.

Rejesta ya udhibiti wa masafa I2C_CCR:

F/S(Uteuzi wa hali kuu ya I2C) - wakati biti hii imewekwa kwa moja, moduli inafanya kazi ndani HARAKA, vinginevyo KIWANGO.

WAJIBU(Mzunguko wa wajibu wa mode ya Fm) - kidogo hii inaweka mzunguko wa wajibu wa ishara SCL katika hali HARAKA. Ikiwa sifuri imewekwa tlow/paja = 2, vinginevyo tlow/paja = 16/9.

CCR(Daftari ya udhibiti wa saa katika hali ya Fm / Sm (Njia ya Mwalimu)) - wakati wa kufanya kazi katika hali ya Mwalimu, huweka mzunguko wa saa ya mstari wa SCL.

Hali ya Sm au SMBus:
Paja = CCR * TPCLK1
Tlow = CCR * TPCLK1

Hali ya FM:
Ikiwa WAJIBU = 0:
Paja = CCR * TPCLK1
Tlow = 2 * CCR * TPCLK1

Ikiwa WAJIBU = 1: (kufikia kHz 400)
Paja = 9 * CCR * TPCLK1
Tlow = 16 * CCR * TPCLK1

Tunapata kwa mode S.M. zifuatazo:
CCR * TPCLK1 + CCR * TPCLK1 = 10,000ns
CCR = 10,000/(2* TPCLK1)

Rejesta ya I2C_TRISE:

TRISE- huamua muda wa kupanda kwa mbele. Imehesabiwa kwa kutumia formula (Tr max/TPCLK1)+1,
Wapi Tr max Kwa S.M. kiasi cha 1000nS, na kwa FM 300nS,
A TPCLK1- kipindi ambacho kinahesabiwa kama 1/ F(APB1).

Rejesta ya kudhibiti kichujio I2C_FLTR:

ANOFF(Kichujio cha kelele cha Analog IMEZIMWA) - sifuri katika kidogo hii huwasha kichujio cha analog.

DNF(Kichujio cha kelele cha dijiti) - uwanja kidogo wa kusanidi kichungi cha dijiti. Kwa maelezo, tafadhali rejelea nyaraka.

Kuanzisha moduli kutoka kwa mradi wa kufanya kazi.
batili I2C2_Init(batili) ( /* SDL -> PB10 SDA -> PB11 RST -> PE15 */ // wezesha uwekaji saa wa milango na moduli ya I2C RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOEEN=RCC_AHB1ENR_GPIOEEN=RCC_GPIOEEN=R1_GPIOEEN; / chaguo la kukokotoa mbadala, pato la kutolea maji wazi, 2 MHz GPIOB->AFR |= (0x04<<2*4); GPIOB->AFR |= (0x04<<3*4); GPIOB->MODER |= GPIO_MODER_MODER10_1; GPIOB->OTYPER |= GPIO_OTYPER_OT_10; GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR10; GPIOB->MODER |= GPIO_MODER_MODER11_1; GPIOB->OTYPER |= GPIO_OTYPER_OT_11; GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR11; //PE15 pato la kusukuma-vuta 50MHz GPIOE->MODER |= GPIO_MODER_MODER15_0; GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR15; AU_RST_HIGH //weka moduli kwa modi ya I2C I2C2->CR1 &= ~2C_CR1_SMBUS; // taja mzunguko wa saa wa moduli I2C2->CR2 &= ~I2C_CR2_FREQ; I2C2->CR2 |= 42; // Fclk1=168/4=42MHz // inasanidi I2C, hali ya kawaida, mzunguko wa wajibu wa KHz 100 1/2 I2C2->CCR &= ~(I2C_CCR_FS | I2C_CCR_DUTY); // weka mzunguko wa uendeshaji wa moduli ya SCL kwa kutumia fomula 10,000nS/(2* TPCLK1) I2C2->CCR |= 208; //10 000ns/48ns = 208 //Standart_Mode = 1000nS, Fast_Mode = 300nS, 1/42MHz = 24nS I2C2->TRISE = 42; //(1000nS/24nS)+1 //washa moduli I2C2->CR1 |= I2C_CR1_PE; ) batili I2C_Write(uint8_t reg_addr, uint8_t data) ( //start I2C2->CR1 |= I2C_CR1_START; while(!(I2C2->SR1 & I2C_SR1_SB))(); (batili) I2C2->SR1; //kupita kifaa anwani I2C2->DR = I2C_ADDRESS(ADDR,I2C_MODE_WRITE) huku(!(I2C2->SR1 & I2C_SR1_ADDR))(); (utupu) I2C2->SR1; (!(I2C2->SR1 & I2C_SR1_TXE))(); //andika data I2C2->DR = data huku(!(I2C2->SR1 & I2C_SR1_BTF))();= I2C_CR1_STOP ) uint8_t I2C_t_ ) ( data ya uint8_t; //anza I2C2->CR1 |= I2C_CR1_START; huku(!(I2C2->SR1 & I2C_SR1_SB))(); (batili) I2C2->SR1; //tuma anwani ya kifaa I2C2->DR = I2C_ADDRESS (ADR,I2C_MODE_WRITE) huku(!(I2C2->SR1 & I2C_SR1_ADDR))() (utupu) I2C2->SR2; I2C2->SR1 & I2C_SR1_TXE)(); I2C2->CR1 |= I2C_CR1_STOP; //sambaza anwani ya kifaa, lakini sasa kwa kusoma I2C2->DR = I2C_ADDRESS(ADR,I2C_MODE_READ); huku(!(I2C2->SR1 & I2C_SR1_ADDR))(); (batili) I2C2->SR1; (batili) I2C2->SR2; //soma I2C2->CR1 &= ~I2C_CR1_ACK; huku(!(I2C2->SR1 & I2C_SR1_RXNE))(); data = I2C2->DR; I2C2->CR1 |= I2C_CR1_STOP; kurudi data; )

Watu wengine wanapenda mikate, wengine hawapendi.

Kiolesura cha i2c kimeenea sana na kinatumika. Katika stm32f4 kuna moduli nyingi kama tatu zinazotekeleza itifaki hii.
Kwa kawaida, kwa msaada kamili kwa suala hili zima.

Kufanya kazi na moduli ni, kwa ujumla, sawa na katika watawala wengine: unaiamuru, inazitekeleza na kuripoti matokeo:
I> Tulikwenda KUANZA.
S> Sawa, nimeituma.
Mimi> Poa, tuma anwani sasa. Kama hii: 0xXX.
S> Sawa, nimeituma. Niliambiwa kwamba ACK. Hebu tuendelee.
I> Bado hai, nzuri. Hapa kuna nambari ya usajili: 0xYY, - twende.
S> Imetumwa, imepokea ACK.
Mimi> Sasa mtumie data, hapa ni byte: 0xZZ.
S> Imetumwa, anakubali zaidi: ACK.
Mimi > Fuck naye, bado. Walienda STOP.
S> Sawa.

Na kila kitu ni takriban katika roho hii.

Katika kidhibiti hiki, pini za i2c zinasambazwa kati ya bandari kama ifuatavyo:
PB6: I2C1_SCL
PB7: I2C1_SDA

PB8: I2C1_SCL
PB9: I2C1_SDA

PB10: I2C2_SCL
PB11: I2C2_SDA

PA8: I2C3_SCL
PC9: I2C3_SDA
Kwa ujumla, ni rahisi kuangalia pinout ya pembeni kwenye ukurasa wa 59.

Kwa kushangaza, kufanya kazi na i2c unahitaji rejista zake zote, kwa bahati nzuri kuna chache kati yao:
I2C_CR1- amri kwa moduli kwa kutuma amri / majimbo na kuchagua njia za uendeshaji;
I2C_CR2- kuanzisha DMA na kuonyesha mzunguko wa uendeshaji wa moduli (2-42 MHz);
I2C_OAR1- kuweka anwani ya kifaa (kwa mtumwa), ukubwa wa anwani (7 au 10 bits);
I2C_OAR2- kuweka anwani ya kifaa (ikiwa kuna anwani mbili);
I2C_DR- rejista ya data;
I2C_SR1- rejista ya hali ya moduli;
I2C_SR2- rejista ya hali (mtumwa, lazima isomwe ikiwa bendera za ADDR au STOPF zimewekwa katika SR1);
I2C_CCR- kuweka kasi ya interface;
I2C_TRISE- kuanzisha nyakati za kingo.

Hata hivyo, nusu yao ni ya aina ya "iandike na uisahau".

Ubao wa STM32F4-Discovery tayari una kifaa cha I2C ambacho unaweza kutumia: CS43L22, DAC ya sauti. Imeunganishwa kwa pini PB6/PB9. Jambo kuu si kusahau kuomba kiwango cha juu cha pini PD4 (~RESET inakaa pale), vinginevyo DAC haitajibu.

Utaratibu wa kuanzisha ni takriban kama ifuatavyo:
1 . Ruhusu kufungwa kwa bandari na moduli yenyewe.
Tunahitaji pini PB6/PB9, kwa hivyo tunahitaji kuweka biti 1 (GPIOBEN) kwenye sajili ya RCC_AHB1ENR ili kuwezesha mlango.
Na uweke biti 21 (I2C1EN) katika sajili ya RCC_APB1ENR ili kuwezesha moduli ya I2C. Kwa moduli ya pili na ya tatu, nambari ndogo ni 22 na 23, mtawaliwa.
2 . Ifuatayo, pini zimesanidiwa: Oped Drain output (GPIO->OTYPER), modi mbadala ya utendakazi (GPIO->MODER), na nambari ya utendakazi mbadala (GPIO->AFR).
Ikiwa inataka, unaweza kusanidi kuvuta-up (GPIO-> PUPDR), ikiwa haipo kwenye ubao (na kuvuta-up kwa usambazaji wa umeme wa mistari yote miwili inahitajika kwa namna yoyote). Nambari ya I2C daima ni sawa: 4. Ni vizuri kuwa kuna nambari tofauti kwa kila aina ya pembeni.
3 . Mzunguko wa saa ya sasa ya pembeni ya Fpclk1 (iliyoonyeshwa kwa MHz) imeonyeshwa kwenye rejista ya CR2. Kama ninavyoielewa, hii inahitajika ili kukokotoa nyakati tofauti za itifaki.
Kwa njia, inapaswa kuwa angalau mbili kwa hali ya kawaida na angalau nne kwa hali ya haraka. Na ikiwa unahitaji kasi kamili ya 400 kHz, basi lazima pia igawanywe na 10 (10, 20, 30, 40 MHz).
Masafa ya juu yanayoruhusiwa ya saa: 42 MHz.
4 . Kasi ya interface imeundwa kwenye rejista ya CCR, na hali imechaguliwa (kawaida / haraka).
Maana ni: Tsck = CCR * 2 * Tpckl1, i.e. kipindi cha SCK ni sawia na CCR (kwa hali ya haraka kila kitu ni gumu zaidi, lakini imeelezewa katika RM).
5 . Muda wa juu zaidi wa ukingo wa kupanda katika rejista ya TRISE hurekebishwa. Kwa hali ya kawaida wakati huu ni 1 µs. Katika rejista unahitaji kuandika idadi ya mizunguko ya basi ambayo inafaa kwa wakati huu, pamoja na moja:
ikiwa mzunguko wa Tpclk1 unachukua 125 ns, basi andika (1000 ns / 125 ns) + 1 = 8 + 1 = 9.
6 . Uzalishaji wa ishara za kukatiza (hitilafu, hali, na data) umewezeshwa kwa hiari;
7 . Moduli huwashwa: bendera ya PE kwenye rejista ya CR1 imewekwa kuwa 1.

Kisha moduli inafanya kazi kama inavyopaswa. Unahitaji tu kutekeleza mpangilio sahihi wa amri na uangalie matokeo. Kwa mfano, ingizo la rejista:
1 . Kwanza unahitaji kutuma ANZA kwa kuweka bendera yenye jina sawa katika rejista ya CR1. Ikiwa kila kitu ni sawa, basi baada ya muda fulani bendera ya SB itawekwa kwenye rejista ya SR1.
Ningependa kutambua jambo moja - ikiwa hakuna kuvuta-juu kwenye mstari (na ziko kwa 0), basi unaweza usingojee bendera hii hata kidogo.
2 . Ikiwa bendera imepokelewa, basi tunatuma anwani. Kwa anwani ya biti saba, tunaiandika kwa DR haswa jinsi itakavyokuwa kwenye mstari (biti 7 za anwani + biti ya mwelekeo). Kwa biti kumi, algorithm ngumu zaidi.
Ikiwa kifaa kinajibu kwa anwani na ACK, basi bendera ya ADDR itaonekana kwenye rejista ya SR1 Ikiwa sivyo, basi bendera ya AF (Kukiri kushindwa) itaonekana.
Ikiwa ADDR inaonekana, unahitaji kusoma rejista ya SR2. Si lazima uangalie chochote hapo, usomaji mfuatano wa SR1 na SR2 huweka upya bendera hii. Na wakati bendera imewekwa, SCL inashikiliwa chini na bwana, ambayo ni muhimu ikiwa unahitaji kuuliza kifaa cha mbali kusubiri kabla ya kutuma data.
Ikiwa kila kitu kiko sawa, basi moduli itabadilika kwa hali ya kupokea au kusambaza data, kulingana na sehemu ndogo ya anwani iliyotumwa. Kwa kuandika lazima iwe sifuri, kwa kusoma lazima iwe moja.
lakini tunaangalia rekodi, kwa hivyo tutadhani kuwa kulikuwa na sifuri hapo.
3 . Kisha tunatuma anwani ya rejista ambayo inatuvutia. Kwa njia hiyo hiyo, kuandika katika DR. Baada ya uhamishaji, bendera za TXE (bafa ya maambukizi haina tupu) na bendera za BTF (uhamisho umekamilika).
4 . Inayofuata inakuja data inayoweza kutumwa wakati kifaa kinajibu kwa ACK. Ikiwa jibu ni NACK, bendera hizi hazitawekwa.
5 . Baada ya kukamilika kwa uhamisho (au katika hali ya hali isiyotarajiwa), tunatuma STOP: bendera ya jina moja imewekwa kwenye rejista ya CR1.

Wakati wa kusoma, kila kitu ni sawa. Mabadiliko tu baada ya kuandika anwani ya rejista.
Badala ya kuandika data, START inatumwa tena (anzisha upya) na anwani inatumwa ikiwa na seti ndogo zaidi (ishara ya kusoma).
Moduli itasubiri data kutoka kwa kifaa. Ili kuihimiza kutuma baiti zinazofuata, unahitaji kuweka bendera ya ACK katika CR1 kabla ya kupokea (ili baada ya kupokea moduli itatuma ACK sawa).
Unapochoka, ondoa bendera, kifaa kitaona NACK na kimya. Baada ya hapo tunatuma STOP kwa njia ya kawaida na kufurahiya data iliyopokelewa.

Hapa kuna kitu sawa katika fomu ya nambari:
// Anzisha utupu wa moduli i2c_Init(batili) ( uint32_t Saa = 16000000UL; // Masafa ya saa ya moduli (system_stm32f4xx.c haitumiki) uint32_t Speed ​​​​= 100000UL; // 100 kHz /> Washa bandari ya AHPICC AHBEN ROB |= RCC_AHB1ENR_GPIOBEN; // Sanidi pini PB6, PB9 // Fungua bomba la GPIOB->OTYPER |= GPIO_OTYPER_OT_9 | GPIOB->Rejesta ya PUPDR // Nambari ya kitendakazi mbadala cha GPIOB ->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; // Katika hatua hii I2C inapaswa kuzimwa // Weka upya kila kitu (SWRST == 1, upya) I2C1->CR1 = I2C_CR1_SWRST; // PE == 0, hii ndiyo jambo kuu I2C1->CR1 = 0; // Tunadhani kwamba tunaendesha kutoka RC (16 MHz) // Hakuna prescaler katika mfumo wa saa (wote 1) // Kwa njia ya kirafiki, tunapaswa kuhesabu yote haya kutoka // mzunguko halisi wa saa ya moduli. I2C1->CR2 = Saa / 1000000UL; // 16 MHz // Rekebisha mzunguko ( // Tclk = (1 / Fperiph); // Paja = Tclk * CCR; // Tlow = Paja; // Fi2c = 1 / CCR * 2; // CCR = Fperiph / (Fi2c * 2) Thamani ya uint16_t (uint16_t) (Saa / (Kasi * 2));< 4) Value = 4; I2C1->CCR = Thamani; ) // Weka muda wa kuongezeka kwa kikomo // Katika hali ya kawaida, wakati huu ni 1000 ns // Tunaongeza tu moja kwa mzunguko ulioonyeshwa katika MHz (angalia RM p. 604). I2C1->TRISE = (Saa / 1000000UL) + 1; // Washa moduli I2C1->CR1 |= (I2C_CR1_PE); // Sasa unaweza kufanya jambo fulani ) // Tuma baiti bool i2c_SendByte(uint8_t Anwani, uint8_t Sajili, uint8_t Data) ( if(!i2c_SendStart()) inarudi sivyo; // Chip address if(!i2c_SendAddress(Anwani)) inarudisha i2c_SendStop (); // Sajili anwani ikiwa(!i2c_SendData(Register)) rudisha i2c_SendStop(// Data if(!i2c_SendData(Data)) rudisha i2c_SendStop(); , uint8_t * Data) ( if(!i2c_SendStart()) inarudisha sivyo; // Anwani ya Chip if(!i2c_SendAddress(Anwani)) itarudisha i2c_SendStop(); // Sajili anwani ikiwa(! i2c_SendData(Register)) rudisha i2c_SendStop(); // Anzisha upya ikiwa(!i2c_SendStart()) rudisha sivyo // Anuani ya Chip (soma) if(!i2c_SendAddress(Anwani | 1)) rudisha i2c_SendStop(); Acha! i2c_SendStop() rudisha kweli (hii lazima ifanyike kwa njia fulani) // Tuma baiti kwa kifaa na anwani 0x94, ili kusajili 0x00 na thamani 0x00. i2c_SendByte(0x94, 0x00, 0x00); // Pokea baiti kutoka kwa kifaa kilicho na anwani 0x94 kutoka kwa rejista 0x01 (Kitambulisho) hadi kwenye bafa inayobadilika i2c_ReceiveByte(0x94, 0x01, &ID); )
Kwa kweli, huwezi kufanya hivi isipokuwa kwa mfano wa mafunzo. Kusubiri kwa hatua kukamilika ni ndefu sana kwa kidhibiti cha haraka kama hicho.

kselltrum Februari 20, 2017 saa 01:17

Hatua za kwanza na STM32 na mkusanyaji wa mikroC wa usanifu wa ARM - Sehemu ya 4 - I2C, pcf8574 na muunganisho wa LCD wa HD4478

  • Programu ya Microcontroller

Ningependa kutoa makala inayofuata kufanya kazi na interface ya kawaida ya i2c, ambayo mara nyingi hutumiwa katika microcircuits mbalimbali zilizounganishwa na microcontroller.

I2C ni basi inayofanya kazi zaidi ya miunganisho miwili ya kimwili (pamoja na waya wa kawaida). Mengi yameandikwa juu yake kwenye mtandao; kuna nakala nzuri kwenye Wikipedia. Kwa kuongeza, algorithm ya uendeshaji wa basi inaelezwa kwa uwazi sana. Kwa kifupi, basi ni basi ya waya mbili ya synchronous. Hadi vifaa 127 vinaweza kuwa kwenye basi kwa wakati mmoja (anwani ya kifaa ni 7-bit, tutarudi kwa hii baadaye). Ifuatayo ni mchoro wa kawaida wa kuunganisha vifaa kwenye basi ya i2c, na MK kama kifaa kikuu.


Kwa i2c, vifaa vyote (bote bwana na watumwa) hutumia matokeo ya bomba wazi. Kuweka tu, wanaweza kuvutia tairi kwa GROUND TU. Kiwango cha juu cha basi kinahakikishwa na vipinga vya kuvuta-up. Thamani ya vipinga hivi kawaida huchaguliwa katika safu kutoka 4.7 hadi 10 kOhm. i2c ni nyeti sana kwa mistari ya kimwili inayounganisha vifaa, hivyo ikiwa unganisho na uwezo mkubwa unatumiwa (kwa mfano, cable ndefu nyembamba au yenye ngao), ushawishi wa uwezo huu unaweza "kuziba" kingo za ishara na kuingilia kati. operesheni ya kawaida ya basi. Kadiri kipinga cha kuvuta-up kikiwa kidogo, ndivyo uwezo huu unavyokuwa na ushawishi mdogo kwenye sifa za kingo za mawimbi, lakini MZIGO KUU kwenye transistors za pato kwenye violesura vya i2c. Thamani ya vipinga hivi huchaguliwa kwa kila utekelezaji maalum, lakini haipaswi kuwa chini ya 2.2 kOhms, vinginevyo unaweza kuchoma tu transistors za pato katika vifaa vinavyofanya kazi na basi.

Basi lina mistari miwili: SDA (mstari wa data) na SCL (ishara ya saa). Saa za kifaa cha Mwalimu wa basi, kwa kawaida MK wetu. Wakati SCL iko juu, habari husomwa kutoka kwa basi ya data. Hali ya SDA inaweza tu kubadilishwa wakati ishara ya saa iko chini.. Wakati SCL iko juu, mawimbi kwenye SDA hubadilika wakati wa kutoa mawimbi ANZA (wakati SCL iko juu ishara kwenye SDA inabadilika kutoka juu hadi chini) na SIMAMA - wakati kiwango cha SCL ni cha juu, ishara kwenye SDA inabadilika kutoka chini hadi juu).

Kando, inapaswa kusemwa kuwa katika i2c anwani imeainishwa kama nambari 7-bit. 8 - kidogo kidogo inaonyesha mwelekeo wa uhamisho wa data 0 - inamaanisha kuwa mtumwa atasambaza data, 1 - kupokea.. Kwa kifupi, algorithm ya kufanya kazi na i2c ni kama ifuatavyo.

  • Kiwango cha juu kwenye SDA na SCL- basi ni bure, unaweza kuanza kufanya kazi
  • Master lifts SCL hadi 1, na kubadilisha hali S.D.A. kutoka 1 hadi 0 - huvutia chini - ishara huundwa ANZA
  • Bwana husambaza anwani ya mtumwa ya 7-bit na mwelekeo kidogo (data kwenye S.D.A. zinaonyeshwa lini SCL kuvutwa chini, na kusomwa na mtumwa wakati inatolewa). Ikiwa mtumwa hawana muda wa "kunyakua" kidogo kilichopita, huvutia SCL chini, na kuifanya iwe wazi kwa bwana kwamba hali ya basi ya data haihitaji kubadilishwa: "Bado ninasoma iliyotangulia." Baada ya bwana kutoa tairi, anakagua mtumwa alimwacha aende zake?.
  • Baada ya kusambaza bits 8 za anwani, bwana hutoa mzunguko wa saa ya 9 na hutoa basi ya data. Ikiwa mtumwa alisikia hotuba yake na akaikubali, basi yeye itabonyeza S.D.A. chini. Hivi ndivyo ishara inavyoundwa ULIZA- imekubaliwa, kila kitu ni sawa. Ikiwa mtumwa haelewi chochote, au hayupo, basi hakutakuwa na mtu wa kushinikiza tairi. bwana atasubiri muda wa kuisha na kuelewa kwamba hakueleweka.
  • Baada ya kupeleka anwani, ikiwa tumeweka mwelekeo kutoka kwa bwana hadi mtumwa(Biti 8 za anwani ni sawa na 1), kisha bwana hupeleka data kwa mtumwa, bila kusahau kuangalia uwepo wa ULIZA kutoka kwa mtumwa, akingojea kifaa cha mtumwa kushughulikia habari zinazoingia.
  • Wakati bwana anapokea data kutoka kwa mtumwa, bwana mwenyewe hutoa ishara ULIZA baada ya kupokea kila byte, na mtumwa anadhibiti uwepo wake. Huenda bwana asitume haswa ULIZA kabla ya kutuma amri SIMAMA, kwa kawaida huweka wazi kwa mtumwa kwamba hakuna haja ya kutoa data yoyote zaidi.
  • Ikiwa, baada ya kutuma data na bwana (mode ya kuandika), ni muhimu kusoma data kutoka kwa mtumwa, kisha bwana hutoa ishara tena ANZA , kutuma anwani ya mtumwa na bendera iliyosomwa. (ikiwa ni kabla ya amri ANZA haikuhamishwa SIMAMA basi timu inaundwa ANZISHA TENA) Hii hutumiwa kubadilisha mwelekeo wa mawasiliano ya bwana-mtumwa. Kwa mfano, tunapitisha anwani ya usajili kwa mtumwa, na kisha kusoma data kutoka kwake.)
  • Baada ya kumaliza kazi na mtumwa, bwana hutoa ishara SIMAMA- kwa kiwango cha juu cha ishara ya saa, huunda mpito wa basi ya data kutoka 0 hadi 1.
STM 32 ina vipitishio vya mabasi vya i2c vilivyotekelezwa na maunzi. Kunaweza kuwa na moduli 2 au 3 katika MK Ili kuzisanidi, rejista maalum hutumiwa, iliyoelezwa katika kumbukumbu ya MK iliyotumiwa.

Katika MicroC, kabla ya kutumia i2c (pamoja na pembeni yoyote), lazima ianzishwe vizuri. Ili kufanya hivyo, tunatumia kazi ifuatayo (Uanzishaji kama bwana):

I2Cn_Init_Advanced(urefu ambao haujasainiwa: I2C_ClockSpeed, const Module_Struct *moduli);

  • n- idadi ya moduli iliyotumiwa, kwa mfano I2C1 au I2C2.
  • I2C_ClockSpeed- kasi ya basi, 100000 (kbs 100, hali ya kawaida) au 400000 (kbs 400, mode ya haraka). Ya pili ni mara 4 kwa kasi, lakini si vifaa vyote vinavyounga mkono
  • *moduli- pointer kwa moduli ya pembeni, kwa mfano &_GPIO_MODULE_I2C1_PB67, tusisahau hapa hilo Msaidizi wa Kanuni (nafasi ya ctrl ) husaidia sana.
Kwanza, hebu tuangalie ikiwa basi ni bure, kuna kazi kwa hili I2Cn_Is_Idle(); kurudisha 1 ikiwa basi ni bure, na 0 ikiwa kuna ubadilishaji juu yake.

I2Cn_Start();
Wapi n- nambari ya moduli ya i2c iliyotumika ya kidhibiti chetu kidogo. Chaguo la kukokotoa litarudi 0 ikiwa kuna hitilafu kwenye basi na 1 ikiwa kila kitu ni sawa.

Ili kuhamisha data kwa mtumwa tunatumia chaguo la kukokotoa:

I2Cn_Write(anwani_ya_char_isiyotiwa saini, char *buf isiyotiwa saini, hesabu ndefu isiyotiwa saini, modi ndefu END_isiyotiwa saini);

  • n- idadi ya moduli iliyotumiwa
  • mtumwa_anwani- 7-bit anwani ya watumwa.
  • *buf- pointer kwa data yetu - safu ya byte au byte.
  • hesabu- idadi ya baiti za data zilizohamishwa.
  • END_modi- nini cha kufanya baada ya kuhamisha data kwa mtumwa, END_MODE_STOP - kusambaza ishara SIMAMA, au END_MODE_RESTART tuma tena ANZA, kutoa ishara ANZISHA TENA na kuweka wazi kwa idara kwamba kikao naye hakijaisha na data zitasomwa kutoka kwake.
Kusoma data kutoka kwa mtumwa, tumia chaguo la kukokotoa:

I2Cn_Read(char slave_anwani, char *ptrdata, hesabu ndefu isiyotiwa saini, modi ndefu END_isiyotiwa saini);

  • n- idadi ya moduli iliyotumiwa
  • mtumwa_anwani- 7-bit anwani ya watumwa.
  • *buf- pointer kwa variable au safu ambayo tunapokea data, chapa char au int fupi
  • hesabu- idadi ya baiti za data zilizopokelewa.
  • END_modi- nini cha kufanya baada ya kupokea data kutoka kwa mtumwa - END_MODE_STOP - kusambaza ishara SIMAMA, au END_MODE_RESTART tuma ishara ANZISHA TENA.
Wacha tujaribu kuunganisha kitu kwenye MK yetu. Kwa kuanzia: PCF8574(A) microcircuit iliyoenea, ambayo ni kipanuzi cha bandari za pembejeo/pato zinazodhibitiwa kupitia basi la i2c. Chip hii ina rejista moja tu ya ndani, ambayo ni bandari yake halisi ya I/O. Hiyo ni, ikiwa unampa byte, itakuwa wazi kwa hitimisho lake mara moja. Ikiwa utahesabu byte kutoka kwayo (Transmit ANZA anwani na bendera ya kusoma, ishara RUDISHA, soma data na mwishowe toa ishara SIMAMA) basi itaakisi hali zenye mantiki kwenye matokeo yake. Wacha tuunganishe microcircuit yetu kwa mujibu wa hifadhidata:


Anwani ya microcircuit huundwa kutoka kwa hali ya pini A0, A1, A2. Kwa microcircuit PCF8574 anwani itakuwa: 0100A0A1A2. (Kwa mfano, tuna A0, A1, A2 kwa kiwango cha juu, kwa mtiririko huo, anwani ya microcircuit yetu itakuwa 0b0100. 111 = 0x27). Kwa PCF8574A - 0111A0A1A2, ambayo kwa mchoro wetu wa uunganisho itatoa anwani 0b0111 111 = 0x3F. Ikiwa, sema, A2 imeunganishwa chini, basi anwani ya PCF8574A mapenzi 0x3B. Kwa jumla, unaweza wakati huo huo kunyongwa microcircuits 16 kwenye basi moja ya i2c, 8 PCF8574A na PCF8574 kila moja.

Hebu tujaribu kuhamisha kitu, kuanzisha basi ya i2c na kuhamisha kitu kwa PCF8574 yetu.

#fafanua PCF8574A_ADDR 0x3F //Anwani ya utupu wetu wa PCF8574 I2C_PCF8574_WriteReg(char wData isiyo na saini) ( I2C1_Start(); // Tengeneza mawimbi ya START I2C1_Write(PCF8574A_A_A_A_A_A_data ya OPEND_A_A) na utengeneze STOP ishara ) char PCF8574A_reg ; // kigezo tunachoandika katika PCF8574 batili kuu () ( I2C1_Init_Advanced(400000, &_GPIO_MODULE_I2C1_PB67); // Anzisha I2C delay_ms(25); // Subiri PCF8574A_reg.b0 = 0; // 8 taa ya kwanza ya LEDA. = 1; // zima LED ya pili huku (1) ( delay_ms(500); PCF8574A_reg.b0 = ~PCF8574A_reg.b0; PCF8574A_reg.b1 = ~PCF8574A_reg.b1; // geuza hali ya LEDs I57Frig4_PCFrig4 ; // kuhamisha data kwa PCF8574 yetu )
Tunakusanya na kuendesha programu yetu na kuona kuwa taa zetu za LED zinapepesa kwa njia mbadala.
Niliunganisha cathode ya LEDs kwa PCF8574 yetu kwa sababu. Jambo ni kwamba wakati mantiki 0 hutolewa kwa pato, microcircuit kwa uaminifu huchota pato lake chini, lakini wakati mantiki 1 inatumiwa, inaunganisha kwa + nguvu kupitia chanzo cha sasa cha 100 μA. Hiyo ni, huwezi kupata "waaminifu" wa kimantiki 1 kwenye pato. Na huwezi kuwasha LED yenye 100 µA. Hii ilifanyika ili kusanidi pato la PCF8574 kwa pembejeo bila rejista za ziada. Tunaandika kwa urahisi rejista ya pato 1 (kwa kuweka vyema majimbo ya pini kuwa Vdd) na tunaweza kufupisha hadi msingi. Chanzo cha sasa hakitaruhusu hatua ya pato la kipanuzi chetu cha I/O "kuchoma". Ikiwa mguu umevutwa chini, basi uwezo wa ardhi ni juu yake, na mantiki 0 inasoma Ikiwa mguu unavutwa kwa +, basi mantiki 1 inasoma kwa upande mmoja. unapaswa kukumbuka hili wakati wa kufanya kazi na microcircuits hizi.


Hebu jaribu kusoma hali ya pini za chip yetu ya kupanua.

#fafanua PCF8574A_ADDR 0x3F //Anwani ya utupu wetu wa PCF8574 I2C_PCF8574_WriteReg(char wData ambayo haijasainiwa) ( I2C1_Start(); // Tengeneza mawimbi ya START I2C1_Write(PCF8574A_A_A_A_A_data ya OPEND_A_A) na utengeneze STOP signal ) batili I2C_PCF8574_ReadReg (char rData ambayo haijasainiwa) ( I2C1_Start(); // Tengeneza mawimbi ya START I2C1_Read(PCF8574A_ADDR, &rData, 1, END_MODE_STOP); // Soma baiti 1 ya data na utengeneze mawimbi ya STOP8 ya PCA_7) //kigeu ambacho tunaandika kwa PCF8574 char PCF8574A_out; // kigezo tulichosoma ndani na PCF8574 char lad_state; // LED yetu imewasha au imezimwa njia kuu isiyo na utupu () ( I2C1_Init_Advanced(400000, &_GPIO_MODULE_I2C1_PB67); // Anzisha I2C delay_ms(25); // Subiri PCF8574A_reg.b0 = 0; // washa taa ya kwanza ya LED PCF85b. 1; // zima ya pili ya LED PCF8574A_reg.b6 = 1 // Unganisha pini 6 na 7 kwa nguvu PCF8574A_reg.b7 = 1; wakati (1) ( delay_ms(100); I2C_PCF8574_WriteReg (PCF8574) PCF8574 I2C_PCF8574_SomaReg (PCF8) 574A_out ); on/off our LED) ikiwa (~PCF8574A_out .b7) PCF8574A_reg.b1 = ~PCF8574A_reg.b1 sawa kwa vitufe 2 na LED 2 ) )
Sasa kwa kushinikiza vifungo tunawasha au kuzima LED yetu. Microcircuit ina pato jingine INT. Mpigo huzalishwa juu yake kila wakati hali ya pini za kipanuzi chetu cha I/O kinapobadilika. Kwa kuiunganisha na pembejeo ya usumbufu wa nje wa MK wetu (Nitakuambia jinsi ya kusanidi usumbufu wa nje na jinsi ya kufanya kazi nao katika moja ya vifungu vifuatavyo).

Hebu tutumie kipanuzi chetu cha bandari kuunganisha onyesho la herufi kupitia hilo. Kuna mengi ya haya, lakini karibu yote yamejengwa kwa msingi wa chip ya mtawala HD44780 na clones zake. Kwa mfano, nilitumia onyesho la LCD2004.


Karatasi ya data yake na kidhibiti cha HD44780 kinaweza kupatikana kwa urahisi kwenye mtandao. Wacha tuunganishe onyesho letu kwa PCF8574, na yake, mtawaliwa, kwa STM32 yetu.

HD44780 hutumia kiolesura cha lango sambamba. Data hupitishwa na 8 (kwa mzunguko wa saa) au 4 (kwa mizunguko ya saa 2) mipigo ya lango kwenye pini. E. (soma na mtawala wa kuonyesha kwenye ukingo wa kushuka, mpito kutoka 1 hadi 0). Hitimisho R.S. inaonyesha ikiwa tunatuma data kwenye onyesho letu ( RS = 1) (herufi ambazo inapaswa kuonyesha ni nambari za ASCII) au amri ( RS = 0). RW inaonyesha mwelekeo wa kuhamisha data, kuandika au kusoma. Kawaida tunaandika data kwenye onyesho, kwa hivyo ( RW=0) Resistor R6 hudhibiti utofautishaji wa onyesho. Huwezi tu kuunganisha pembejeo ya urekebishaji wa utofautishaji kwenye ardhi au nguvu, vinginevyo hutaona chochote.. VT1 hutumika kuwasha na kuzima taa ya nyuma kulingana na amri za MK. MicroC ina maktaba ya kufanya kazi na maonyesho kama haya kupitia kiolesura sambamba, lakini kawaida ni ghali kutumia miguu 8 kwenye onyesho, kwa hivyo karibu kila wakati ninatumia PCF8574 kufanya kazi na skrini kama hizo. (Ikiwa mtu yeyote ana nia, nitaandika makala kuhusu kufanya kazi na maonyesho ya HD44780 yaliyojengwa kwenye MicroC kupitia interface sambamba.) Itifaki ya kubadilishana sio ngumu hasa (tutatumia mistari 4 ya data na kuhamisha habari katika mzunguko wa saa 2), inaonyeshwa wazi na mchoro ufuatao wa wakati:


Kabla ya kuhamisha data kwenye onyesho letu, lazima ianzishwe kwa kupitisha amri za huduma. (imefafanuliwa kwenye hifadhidata, hapa tunawasilisha zile zinazotumiwa zaidi)

  • 0x28- mawasiliano na kiashiria kupitia mistari 4
  • 0x0C- Wezesha pato la picha, afya ya kuonyesha mshale
  • 0x0E- Wezesha pato la picha, wezesha onyesho la mshale
  • 0x01- wazi kiashiria
  • 0x08- Lemaza pato la picha
  • 0x06- baada ya ishara kuonyeshwa, mshale husogea na mahali 1 inayojulikana
Kwa kuwa tutahitaji kufanya kazi na kiashiria hiki mara nyingi, tutaunda maktaba ya kuziba "i2c_lcd.h" . Kwa kusudi hili katika Meneja wa mradi Faili za Kichwa na kuchagua Ongeza Faili Mpya . Wacha tuunde faili yetu ya kichwa.

#fafanua PCF8574A_ADDR 0x3F //Anwani ya PCF8574 yetu #fafanua DB4 b4 // Mawasiliano kati ya pini za PCF8574 na kiashirio #fafanua DB5 b5 #fafanua DB6 b6 #fafanua DB7 b7 #fafanua #fafanua bW2 #fafanua EN BW2RSS BL b0 // udhibiti wa taa za nyuma #fafanua displenth 20 // idadi ya herufi katika mstari wetu wa kuonyesha tuli ambao haujasainiwa char BL_status; // kutofautiana kuhifadhi hali ya backlight (on/off) batili lcd_I2C_Init(batili); // Display na PCF8574 uanzishaji kazi batili lcd_I2C_txt(char *pnt); // Inaonyesha mstari wa maandishi, parameter ni pointer kwa mstari huu utupu lcd_I2C_int(int pnt); // Huonyesha thamani ya kigezo kamili, kigezo ni utupu wa thamani ya pato lcd_I2C_Goto (safu fupi isiyo na saini, safu fupi isiyotiwa saini); // husogeza mshale kwa nafasi maalum, safu ya vigezo - mstari (kutoka 1 hadi 2 au 4 kulingana na onyesho) na col - (kutoka 1 hadi displenth)) batili lcd_I2C_cls(); // Hufuta utupu wa skrini lcd_I2C_backlight (hali fupi isiyo na saini ya int); // Inawasha (wakati wa kusambaza 1 na kulemaza - wakati wa kusambaza 0 taa ya nyuma ya onyesho)
Sasa hebu tueleze kazi zetu, tena tunaenda Meneja wa mradi bonyeza kulia kwenye folda Vyanzo na kuchagua Ongeza Faili Mpya . Unda faili "i2c_lcd.с" .

#jumuisha "i2c_lcd.h" //pamoja na faili yetu ya kichwa char lcd_reg; // Rejesta ya hifadhi ya muda ya data iliyotumwa kwa PCF8574 VOID I2C_PCF8574_WRITEREG (UNSIGNED ChaR WDATA) // Kazi ya data ya I2C katika chipu ya PCF8574 (I2C1_START (); i2C1_WRITE (PCF8574A_A_A_A_ATA_END_END_END_); amri kwa onyesho letu ( lcd_reg = 0; // andika 0 kwa rejista ya muda lcd_reg.BL = BL_status.b0; //weka pini ya taa ya nyuma kwa mujibu wa thamani ya utofauti unaohifadhi hali ya taa ya nyuma lcd_reg.DB4 = com. b4; // kuweka bits 4 muhimu zaidi kwa basi data kiashiria lcd_reg.DB5 = lcd_reg.DB7 = com.b7; Rejesta ya PCF8574, kwa kweli kutuma data kwa kiashiria kuchelewa_us (300) lcd_reg.EN = 0, kiashiria kinasoma data I2C_PCF8574_WriteReg (lcd_reg ; .BL = BL_status.b0; lcd_reg.DB4 = com.b0; //same kwa bits 4 za chini lcd_reg.DB5 = com.b1; lcd_reg.DB6 = com.b2; lcd_reg.DB7 = com.b3; lcd_reg.EN = 1; I2C_PCF8574_WriteReg(lcd_reg); kuchelewesha_sisi(300); lcd_reg.EN = 0; I2C_PCF8574_WriteReg(lcd_reg); kuchelewesha_sisi(300); ) batili LCD_CHAR (char com ambayo haijasainiwa) //kutuma data (msimbo wa herufi ASCII) kwa kiashirio ( lcd_reg = 0; lcd_reg.BL = BL_status.b0; lcd_reg.EN = 1; lcd_reg.RS = 1; //kutuma herufi ni tofauti na kutuma amri kwa kuweka biti ya RS kuwa 1 lcd_reg.DB4 = com.b4; 300); lcd_reg.EN = 0; // weka upya strobe hadi 0, kiashiria kinasoma data I2C_PCF8574_Reg (lcd_reg.RS = 1; .DB5 = com.b1; lcd_reg.DB7 = com.b3 delay_us (lcd_reg.EN = 0; 200) ;lcd_Command(0x28); // Onyesha kwa biti 4 kwa kila hali ya saa delay_ms (5); lcd_Command(0x08); // Lemaza pato la data kwa onyesho delay_ms (5); lcd_Command(0x01); //Futa onyesho delay_ms (5); lcd_Command(0x06); //Wezesha mabadiliko ya kielekezi kiotomatiki baada ya kuonyesha alama ya delay_ms (5); lcd_Command(0x0C); //Washa kuonyesha maelezo bila kuonyesha delay_ms ya kishale (25); ) void lcd_I2C_txt(char *pnt) //Onyesha mfuatano wa herufi kwenye onyesho ( int i fupi isiyo na saini; // safu ya herufi ya muda ya kielezo cha kutofautiana char tmp_str; // safu ya muda ya herufi, urefu 1 zaidi ya urefu wa onyesho. mstari, kwa kuwa mstari unahitaji kusitishwa сiv kwa herufi NULL ASCII 0x00 strncpy(tmp_str, pnt, displenth); Sasa hebu tuunganishe maktaba mpya iliyoundwa na faili na kazi yetu kuu:

#jumuisha "i2c_lcd.h" //jumuisha faili yetu ya kichwa ambayo haijasainiwa int i; //kiunzi kizito cha muda cha utupu () ( lcd_I2C_Init(); //anzisha onyesho lcd_I2C_backlight (1); //washa taa ya nyuma lcd_I2C_txt ("Hujambo habrahabr"); // onyesha laini wakati (1) ( delay_ms( 1000) lcd_I2C_Goto (2,1) nenda kwa herufi ya 1 ya mstari wa 2 lcd_i2c_int (i)

Ikiwa kila kitu kimekusanywa kwa usahihi, basi tunapaswa kuona maandishi kwenye kiashiria na kuongeza kihesabu kila sekunde. Kwa ujumla, hakuna kitu ngumu :)

Katika makala inayofuata tutaendelea kuelewa itifaki ya i2c na vifaa vinavyofanya kazi nayo. Hebu tufikirie kufanya kazi na kumbukumbu ya EEPROM 24XX na kipima kasi cha MPU6050/gyroscope.

Hatua za kwanza na STM32 na mkusanyaji wa mikroC wa usanifu wa ARM - Sehemu ya 4 - I2C, pcf8574 na muunganisho wa LCD wa HD4478

Ningependa kutoa makala inayofuata kufanya kazi na interface ya kawaida ya i2c, ambayo mara nyingi hutumiwa katika microcircuits mbalimbali zilizounganishwa na microcontroller.

I2C ni basi inayofanya kazi zaidi ya miunganisho miwili ya kimwili (pamoja na waya wa kawaida). Mengi yameandikwa juu yake kwenye mtandao; kuna nakala nzuri kwenye Wikipedia. Kwa kuongeza, algorithm ya uendeshaji wa basi inaelezwa kwa uwazi sana. Kwa kifupi, basi ni basi ya waya mbili ya synchronous. Hadi vifaa 127 vinaweza kuwa kwenye basi kwa wakati mmoja (anwani ya kifaa ni 7-bit, tutarudi kwa hii baadaye). Ifuatayo ni mchoro wa kawaida wa kuunganisha vifaa kwenye basi ya i2c, na MK kama kifaa kikuu.


Kwa i2c, vifaa vyote (bote bwana na watumwa) hutumia matokeo ya bomba wazi. Kuweka tu, wanaweza kuvutia tairi kwa GROUND TU. Kiwango cha juu cha basi kinahakikishwa na vipinga vya kuvuta-up. Thamani ya vipinga hivi kawaida huchaguliwa katika safu kutoka 4.7 hadi 10 kOhm. i2c ni nyeti sana kwa mistari ya kimwili inayounganisha vifaa, hivyo ikiwa unganisho na uwezo mkubwa unatumiwa (kwa mfano, cable ndefu nyembamba au yenye ngao), ushawishi wa uwezo huu unaweza "kuziba" kingo za ishara na kuingilia kati. operesheni ya kawaida ya basi. Kadiri kipinga cha kuvuta-up kikiwa kidogo, ndivyo uwezo huu unavyokuwa na ushawishi mdogo kwenye sifa za kingo za mawimbi, lakini MZIGO KUU kwenye transistors za pato kwenye violesura vya i2c. Thamani ya vipinga hivi huchaguliwa kwa kila utekelezaji maalum, lakini haipaswi kuwa chini ya 2.2 kOhms, vinginevyo unaweza kuchoma tu transistors za pato katika vifaa vinavyofanya kazi na basi.

Basi lina mistari miwili: SDA (mstari wa data) na SCL (ishara ya saa). Saa za kifaa cha Mwalimu wa basi, kwa kawaida MK wetu. Wakati SCL iko juu, habari husomwa kutoka kwa basi ya data. Hali ya SDA inaweza tu kubadilishwa wakati ishara ya saa iko chini.. Wakati SCL iko juu, mawimbi kwenye SDA hubadilika wakati wa kutoa mawimbi ANZA (wakati SCL iko juu ishara kwenye SDA inabadilika kutoka juu hadi chini) na SIMAMA - wakati kiwango cha SCL ni cha juu, ishara kwenye SDA inabadilika kutoka chini hadi juu).

Kando, inapaswa kusemwa kuwa katika i2c anwani imeainishwa kama nambari 7-bit. 8 - kidogo kidogo inaonyesha mwelekeo wa uhamisho wa data 0 - inamaanisha kuwa mtumwa atasambaza data, 1 - kupokea.. Kwa kifupi, algorithm ya kufanya kazi na i2c ni kama ifuatavyo.

  • Kiwango cha juu kwenye SDA na SCL- basi ni bure, unaweza kuanza kufanya kazi
  • Master lifts SCL hadi 1, na kubadilisha hali S.D.A. kutoka 1 hadi 0 - huvutia chini - ishara huundwa ANZA
  • Bwana husambaza anwani ya mtumwa ya 7-bit na mwelekeo kidogo (data kwenye S.D.A. zinaonyeshwa lini SCL kuvutwa chini, na kusomwa na mtumwa wakati inatolewa). Ikiwa mtumwa hawana muda wa "kunyakua" kidogo kilichopita, huvutia SCL chini, na kuifanya iwe wazi kwa bwana kwamba hali ya basi ya data haihitaji kubadilishwa: "Bado ninasoma iliyotangulia." Baada ya bwana kutoa tairi, anakagua mtumwa alimwacha aende zake?.
  • Baada ya kusambaza bits 8 za anwani, bwana hutoa mzunguko wa saa ya 9 na hutoa basi ya data. Ikiwa mtumwa alisikia hotuba yake na akaikubali, basi yeye itabonyeza S.D.A. chini. Hivi ndivyo ishara inavyoundwa ULIZA- imekubaliwa, kila kitu ni sawa. Ikiwa mtumwa haelewi chochote, au hayupo, basi hakutakuwa na mtu wa kushinikiza tairi. bwana atasubiri muda wa kuisha na kuelewa kwamba hakueleweka.
  • Baada ya kupeleka anwani, ikiwa tumeweka mwelekeo kutoka kwa bwana hadi mtumwa(Biti 8 za anwani ni sawa na 1), kisha bwana hupeleka data kwa mtumwa, bila kusahau kuangalia uwepo wa ULIZA kutoka kwa mtumwa, akingojea kifaa cha mtumwa kushughulikia habari zinazoingia.
  • Wakati bwana anapokea data kutoka kwa mtumwa, bwana mwenyewe hutoa ishara ULIZA baada ya kupokea kila byte, na mtumwa anadhibiti uwepo wake. Huenda bwana asitume haswa ULIZA kabla ya kutuma amri SIMAMA, kwa kawaida huweka wazi kwa mtumwa kwamba hakuna haja ya kutoa data yoyote zaidi.
  • Ikiwa, baada ya kutuma data na bwana (mode ya kuandika), ni muhimu kusoma data kutoka kwa mtumwa, kisha bwana hutoa ishara tena ANZA , kutuma anwani ya mtumwa na bendera iliyosomwa. (ikiwa ni kabla ya amri ANZA haikuhamishwa SIMAMA basi timu inaundwa ANZISHA TENA) Hii hutumiwa kubadilisha mwelekeo wa mawasiliano ya bwana-mtumwa. Kwa mfano, tunapitisha anwani ya usajili kwa mtumwa, na kisha kusoma data kutoka kwake.)
  • Baada ya kumaliza kazi na mtumwa, bwana hutoa ishara SIMAMA- kwa kiwango cha juu cha ishara ya saa, huunda mpito wa basi ya data kutoka 0 hadi 1.
STM 32 ina vipitishio vya mabasi vya i2c vilivyotekelezwa na maunzi. Kunaweza kuwa na moduli 2 au 3 katika MK Ili kuzisanidi, rejista maalum hutumiwa, iliyoelezwa katika kumbukumbu ya MK iliyotumiwa.

Katika MicroC, kabla ya kutumia i2c (pamoja na pembeni yoyote), lazima ianzishwe vizuri. Ili kufanya hivyo, tunatumia kazi ifuatayo (Uanzishaji kama bwana):

I2Cn_Init_Advanced(urefu ambao haujasainiwa: I2C_ClockSpeed, const Module_Struct *moduli);

  • n- idadi ya moduli iliyotumiwa, kwa mfano I2C1 au I2C2.
  • I2C_ClockSpeed- kasi ya basi, 100000 (kbs 100, hali ya kawaida) au 400000 (kbs 400, mode ya haraka). Ya pili ni mara 4 kwa kasi, lakini si vifaa vyote vinavyounga mkono
  • *moduli- pointer kwa moduli ya pembeni, kwa mfano &_GPIO_MODULE_I2C1_PB67, tusisahau hapa hilo Msaidizi wa Kanuni (nafasi ya ctrl ) husaidia sana.
Kwanza, hebu tuangalie ikiwa basi ni bure, kuna kazi kwa hili I2Cn_Is_Idle(); kurudisha 1 ikiwa basi ni bure, na 0 ikiwa kuna ubadilishaji juu yake.

I2Cn_Start();
Wapi n- nambari ya moduli ya i2c iliyotumika ya kidhibiti chetu kidogo. Chaguo la kukokotoa litarudi 0 ikiwa kuna hitilafu kwenye basi na 1 ikiwa kila kitu ni sawa.

Ili kuhamisha data kwa mtumwa tunatumia chaguo la kukokotoa:

I2Cn_Write(anwani_ya_char_isiyotiwa saini, char *buf isiyotiwa saini, hesabu ndefu isiyotiwa saini, modi ndefu END_isiyotiwa saini);

  • n- idadi ya moduli iliyotumiwa
  • mtumwa_anwani- 7-bit anwani ya watumwa.
  • *buf- pointer kwa data yetu - safu ya byte au byte.
  • hesabu- idadi ya baiti za data zilizohamishwa.
  • END_modi- nini cha kufanya baada ya kuhamisha data kwa mtumwa, END_MODE_STOP - kusambaza ishara SIMAMA, au END_MODE_RESTART tuma tena ANZA, kutoa ishara ANZISHA TENA na kuweka wazi kwa idara kwamba kikao naye hakijaisha na data zitasomwa kutoka kwake.
Kusoma data kutoka kwa mtumwa, tumia chaguo la kukokotoa:

I2Cn_Read(char slave_anwani, char *ptrdata, hesabu ndefu isiyotiwa saini, modi ndefu END_isiyotiwa saini);

  • n- idadi ya moduli iliyotumiwa
  • mtumwa_anwani- 7-bit anwani ya watumwa.
  • *buf- pointer kwa variable au safu ambayo tunapokea data, chapa char au int fupi
  • hesabu- idadi ya baiti za data zilizopokelewa.
  • END_modi- nini cha kufanya baada ya kupokea data kutoka kwa mtumwa - END_MODE_STOP - kusambaza ishara SIMAMA, au END_MODE_RESTART tuma ishara ANZISHA TENA.
Wacha tujaribu kuunganisha kitu kwenye MK yetu. Kwa kuanzia: PCF8574(A) microcircuit iliyoenea, ambayo ni kipanuzi cha bandari za pembejeo/pato zinazodhibitiwa kupitia basi la i2c. Chip hii ina rejista moja tu ya ndani, ambayo ni bandari yake halisi ya I/O. Hiyo ni, ikiwa unampa byte, itakuwa wazi kwa hitimisho lake mara moja. Ikiwa utahesabu byte kutoka kwayo (Transmit ANZA anwani na bendera ya kusoma, ishara RUDISHA, soma data na mwishowe toa ishara SIMAMA) basi itaakisi hali zenye mantiki kwenye matokeo yake. Wacha tuunganishe microcircuit yetu kwa mujibu wa hifadhidata:


Anwani ya microcircuit huundwa kutoka kwa hali ya pini A0, A1, A2. Kwa microcircuit PCF8574 anwani itakuwa: 0100A0A1A2. (Kwa mfano, tuna A0, A1, A2 kwa kiwango cha juu, kwa mtiririko huo, anwani ya microcircuit yetu itakuwa 0b0100. 111 = 0x27). Kwa PCF8574A - 0111A0A1A2, ambayo kwa mchoro wetu wa uunganisho itatoa anwani 0b0111 111 = 0x3F. Ikiwa, sema, A2 imeunganishwa chini, basi anwani ya PCF8574A mapenzi 0x3B. Kwa jumla, unaweza wakati huo huo kunyongwa microcircuits 16 kwenye basi moja ya i2c, 8 PCF8574A na PCF8574 kila moja.

Hebu tujaribu kuhamisha kitu, kuanzisha basi ya i2c na kuhamisha kitu kwa PCF8574 yetu.

#fafanua PCF8574A_ADDR 0x3F //Anwani ya utupu wetu wa PCF8574 I2C_PCF8574_WriteReg(char wData isiyo na saini) ( I2C1_Start(); // Tengeneza mawimbi ya START I2C1_Write(PCF8574A_A_A_A_A_A_data ya OPEND_A_A) na utengeneze STOP ishara ) char PCF8574A_reg ; // kigezo tunachoandika katika PCF8574 batili kuu () ( I2C1_Init_Advanced(400000, &_GPIO_MODULE_I2C1_PB67); // Anzisha I2C delay_ms(25); // Subiri PCF8574A_reg.b0 = 0; // 8 taa ya kwanza ya LEDA. = 1; // zima LED ya pili huku (1) ( delay_ms(500); PCF8574A_reg.b0 = ~PCF8574A_reg.b0; PCF8574A_reg.b1 = ~PCF8574A_reg.b1; // geuza hali ya LEDs I57Frig4_PCFrig4 ; // kuhamisha data kwa PCF8574 yetu )
Tunakusanya na kuendesha programu yetu na kuona kuwa taa zetu za LED zinapepesa kwa njia mbadala.
Niliunganisha cathode ya LEDs kwa PCF8574 yetu kwa sababu. Jambo ni kwamba wakati mantiki 0 hutolewa kwa pato, microcircuit kwa uaminifu huchota pato lake chini, lakini wakati mantiki 1 inatumiwa, inaunganisha kwa + nguvu kupitia chanzo cha sasa cha 100 μA. Hiyo ni, huwezi kupata "waaminifu" wa kimantiki 1 kwenye pato. Na huwezi kuwasha LED yenye 100 µA. Hii ilifanyika ili kusanidi pato la PCF8574 kwa pembejeo bila rejista za ziada. Tunaandika kwa urahisi rejista ya pato 1 (kwa kuweka vyema majimbo ya pini kuwa Vdd) na tunaweza kufupisha hadi msingi. Chanzo cha sasa hakitaruhusu hatua ya pato la kipanuzi chetu cha I/O "kuchoma". Ikiwa mguu umevutwa chini, basi uwezo wa ardhi ni juu yake, na mantiki 0 inasoma Ikiwa mguu unavutwa kwa +, basi mantiki 1 inasoma kwa upande mmoja. unapaswa kukumbuka hili wakati wa kufanya kazi na microcircuits hizi.


Hebu jaribu kusoma hali ya pini za chip yetu ya kupanua.

#fafanua PCF8574A_ADDR 0x3F //Anwani ya utupu wetu wa PCF8574 I2C_PCF8574_WriteReg(char wData ambayo haijasainiwa) ( I2C1_Start(); // Tengeneza mawimbi ya START I2C1_Write(PCF8574A_A_A_A_A_data ya OPEND_A_A) na utengeneze STOP signal ) batili I2C_PCF8574_ReadReg (char rData ambayo haijasainiwa) ( I2C1_Start(); // Tengeneza mawimbi ya START I2C1_Read(PCF8574A_ADDR, &rData, 1, END_MODE_STOP); // Soma baiti 1 ya data na utengeneze mawimbi ya STOP8 ya PCA_7) //kigeu ambacho tunaandika kwa PCF8574 char PCF8574A_out; // kigezo tulichosoma ndani na PCF8574 char lad_state; // LED yetu imewasha au imezimwa njia kuu isiyo na utupu () ( I2C1_Init_Advanced(400000, &_GPIO_MODULE_I2C1_PB67); // Anzisha I2C delay_ms(25); // Subiri PCF8574A_reg.b0 = 0; // washa taa ya kwanza ya LED PCF85b. 1; // zima ya pili ya LED PCF8574A_reg.b6 = 1 // Unganisha pini 6 na 7 kwa nguvu PCF8574A_reg.b7 = 1; wakati (1) ( delay_ms(100); I2C_PCF8574_WriteReg (PCF8574) PCF8574 I2C_PCF8574_SomaReg (PCF8) 574A_out ); on/off our LED) ikiwa (~PCF8574A_out .b7) PCF8574A_reg.b1 = ~PCF8574A_reg.b1 sawa kwa vitufe 2 na LED 2 ) )
Sasa kwa kushinikiza vifungo tunawasha au kuzima LED yetu. Microcircuit ina pato jingine INT. Mpigo huzalishwa juu yake kila wakati hali ya pini za kipanuzi chetu cha I/O kinapobadilika. Kwa kuiunganisha na pembejeo ya usumbufu wa nje wa MK wetu (Nitakuambia jinsi ya kusanidi usumbufu wa nje na jinsi ya kufanya kazi nao katika moja ya vifungu vifuatavyo).

Hebu tutumie kipanuzi chetu cha bandari kuunganisha onyesho la herufi kupitia hilo. Kuna mengi ya haya, lakini karibu yote yamejengwa kwa msingi wa chip ya mtawala HD44780 na clones zake. Kwa mfano, nilitumia onyesho la LCD2004.


Karatasi ya data yake na kidhibiti cha HD44780 kinaweza kupatikana kwa urahisi kwenye mtandao. Wacha tuunganishe onyesho letu kwa PCF8574, na yake, mtawaliwa, kwa STM32 yetu.

HD44780 hutumia kiolesura cha lango sambamba. Data hupitishwa na 8 (kwa mzunguko wa saa) au 4 (kwa mizunguko ya saa 2) mipigo ya lango kwenye pini. E. (soma na mtawala wa kuonyesha kwenye ukingo wa kushuka, mpito kutoka 1 hadi 0). Hitimisho R.S. inaonyesha ikiwa tunatuma data kwenye onyesho letu ( RS = 1) (herufi ambazo inapaswa kuonyesha ni nambari za ASCII) au amri ( RS = 0). RW inaonyesha mwelekeo wa kuhamisha data, kuandika au kusoma. Kawaida tunaandika data kwenye onyesho, kwa hivyo ( RW=0) Resistor R6 hudhibiti utofautishaji wa onyesho. Huwezi tu kuunganisha pembejeo ya urekebishaji wa utofautishaji kwenye ardhi au nguvu, vinginevyo hutaona chochote.. VT1 hutumika kuwasha na kuzima taa ya nyuma kulingana na amri za MK. MicroC ina maktaba ya kufanya kazi na maonyesho kama haya kupitia kiolesura sambamba, lakini kawaida ni ghali kutumia miguu 8 kwenye onyesho, kwa hivyo karibu kila wakati ninatumia PCF8574 kufanya kazi na skrini kama hizo. (Ikiwa mtu yeyote ana nia, nitaandika makala kuhusu kufanya kazi na maonyesho ya HD44780 yaliyojengwa kwenye MicroC kupitia interface sambamba.) Itifaki ya kubadilishana sio ngumu hasa (tutatumia mistari 4 ya data na kuhamisha habari katika mzunguko wa saa 2), inaonyeshwa wazi na mchoro ufuatao wa wakati:


Kabla ya kuhamisha data kwenye onyesho letu, lazima ianzishwe kwa kupitisha amri za huduma. (imefafanuliwa kwenye hifadhidata, hapa tunawasilisha zile zinazotumiwa zaidi)

  • 0x28- mawasiliano na kiashiria kupitia mistari 4
  • 0x0C- Wezesha pato la picha, afya ya kuonyesha mshale
  • 0x0E- Wezesha pato la picha, wezesha onyesho la mshale
  • 0x01- wazi kiashiria
  • 0x08- Lemaza pato la picha
  • 0x06- baada ya ishara kuonyeshwa, mshale husogea na mahali 1 inayojulikana
Kwa kuwa tutahitaji kufanya kazi na kiashiria hiki mara nyingi, tutaunda maktaba ya kuziba "i2c_lcd.h" . Kwa kusudi hili katika Meneja wa mradi Faili za Kichwa na kuchagua Ongeza Faili Mpya . Wacha tuunde faili yetu ya kichwa.

#fafanua PCF8574A_ADDR 0x3F //Anwani ya PCF8574 yetu #fafanua DB4 b4 // Mawasiliano kati ya pini za PCF8574 na kiashirio #fafanua DB5 b5 #fafanua DB6 b6 #fafanua DB7 b7 #fafanua #fafanua bW2 #fafanua EN BW2RSS BL b0 // udhibiti wa taa za nyuma #fafanua displenth 20 // idadi ya herufi katika mstari wetu wa kuonyesha tuli ambao haujasainiwa char BL_status; // kutofautiana kuhifadhi hali ya backlight (on/off) batili lcd_I2C_Init(batili); // Display na PCF8574 uanzishaji kazi batili lcd_I2C_txt(char *pnt); // Inaonyesha mstari wa maandishi, parameter ni pointer kwa mstari huu utupu lcd_I2C_int(int pnt); // Huonyesha thamani ya kigezo kamili, kigezo ni utupu wa thamani ya pato lcd_I2C_Goto (safu fupi isiyo na saini, safu fupi isiyotiwa saini); // husogeza mshale kwa nafasi maalum, safu ya vigezo - mstari (kutoka 1 hadi 2 au 4 kulingana na onyesho) na col - (kutoka 1 hadi displenth)) batili lcd_I2C_cls(); // Hufuta utupu wa skrini lcd_I2C_backlight (hali fupi isiyo na saini ya int); // Inawasha (wakati wa kusambaza 1 na kulemaza - wakati wa kusambaza 0 taa ya nyuma ya onyesho)
Sasa hebu tueleze kazi zetu, tena tunaenda Meneja wa mradi bonyeza kulia kwenye folda Vyanzo na kuchagua Ongeza Faili Mpya . Unda faili "i2c_lcd.с" .

#jumuisha "i2c_lcd.h" //pamoja na faili yetu ya kichwa char lcd_reg; // Rejesta ya hifadhi ya muda ya data iliyotumwa kwa PCF8574 VOID I2C_PCF8574_WRITEREG (UNSIGNED ChaR WDATA) // Kazi ya data ya I2C katika chipu ya PCF8574 (I2C1_START (); i2C1_WRITE (PCF8574A_A_A_A_ATA_END_END_END_); amri kwa onyesho letu ( lcd_reg = 0; // andika 0 kwa rejista ya muda lcd_reg.BL = BL_status.b0; //weka pini ya taa ya nyuma kwa mujibu wa thamani ya utofauti unaohifadhi hali ya taa ya nyuma lcd_reg.DB4 = com. b4; // kuweka bits 4 muhimu zaidi kwa basi data kiashiria lcd_reg.DB5 = lcd_reg.DB7 = com.b7; Rejesta ya PCF8574, kwa kweli kutuma data kwa kiashiria kuchelewa_us (300) lcd_reg.EN = 0, kiashiria kinasoma data I2C_PCF8574_WriteReg (lcd_reg ; .BL = BL_status.b0; lcd_reg.DB4 = com.b0; //same kwa bits 4 za chini lcd_reg.DB5 = com.b1; lcd_reg.DB6 = com.b2; lcd_reg.DB7 = com.b3; lcd_reg.EN = 1; I2C_PCF8574_WriteReg(lcd_reg); kuchelewesha_sisi(300); lcd_reg.EN = 0; I2C_PCF8574_WriteReg(lcd_reg); kuchelewesha_sisi(300); ) batili LCD_CHAR (char com ambayo haijasainiwa) //kutuma data (msimbo wa herufi ASCII) kwa kiashirio ( lcd_reg = 0; lcd_reg.BL = BL_status.b0; lcd_reg.EN = 1; lcd_reg.RS = 1; //kutuma herufi ni tofauti na kutuma amri kwa kuweka biti ya RS kuwa 1 lcd_reg.DB4 = com.b4; 300); lcd_reg.EN = 0; // weka upya strobe hadi 0, kiashiria kinasoma data I2C_PCF8574_Reg (lcd_reg.RS = 1; .DB5 = com.b1; lcd_reg.DB7 = com.b3 delay_us (lcd_reg.EN = 0; 200) ;lcd_Command(0x28); // Onyesha kwa biti 4 kwa kila hali ya saa delay_ms (5); lcd_Command(0x08); // Lemaza pato la data kwa onyesho delay_ms (5); lcd_Command(0x01); //Futa onyesho delay_ms (5); lcd_Command(0x06); //Wezesha mabadiliko ya kielekezi kiotomatiki baada ya kuonyesha alama ya delay_ms (5); lcd_Command(0x0C); //Washa kuonyesha maelezo bila kuonyesha delay_ms ya kishale (25); ) void lcd_I2C_txt(char *pnt) //Onyesha mfuatano wa herufi kwenye onyesho ( int i fupi isiyo na saini; // safu ya herufi ya muda ya kielezo cha kutofautiana char tmp_str; // safu ya muda ya herufi, urefu 1 zaidi ya urefu wa onyesho. mstari, kwa kuwa mstari unahitaji kusitishwa сiv kwa herufi NULL ASCII 0x00 strncpy(tmp_str, pnt, displenth); Sasa hebu tuunganishe maktaba mpya iliyoundwa na faili na kazi yetu kuu:

#jumuisha "i2c_lcd.h" //jumuisha faili yetu ya kichwa ambayo haijasainiwa int i; //kiunzi kizito cha muda cha utupu () ( lcd_I2C_Init(); //anzisha onyesho lcd_I2C_backlight (1); //washa taa ya nyuma lcd_I2C_txt ("Hujambo habrahabr"); // onyesha laini wakati (1) ( delay_ms( 1000) lcd_I2C_Goto (2,1) nenda kwa herufi ya 1 ya mstari wa 2 lcd_i2c_int (i)

Ikiwa kila kitu kimekusanywa kwa usahihi, basi tunapaswa kuona maandishi kwenye kiashiria na kuongeza kihesabu kila sekunde. Kwa ujumla, hakuna kitu ngumu :)

Katika makala inayofuata tutaendelea kuelewa itifaki ya i2c na vifaa vinavyofanya kazi nayo. Hebu tufikirie kufanya kazi na kumbukumbu ya EEPROM 24XX na kipima kasi cha MPU6050/gyroscope.

Iliyochapishwa 10/26/2016

Katika makala iliyotangulia tuliangalia utendakazi wa STM32 na basi la I 2 C kama Master. Hiyo ni, alikuwa kiongozi na alihoji sensor. Sasa wacha tuifanye STM32 kuwa Mtumwa na kujibu maombi, ambayo ni kwamba, yenyewe inafanya kazi kama kihisi. Tutatenga baiti 255 za kumbukumbu kwa rejista zilizo na anwani kutoka 0 hadi 0xFF, na kumruhusu Mwalimu kuziandika / kuzisoma. Na kufanya mfano usiwe rahisi sana, wacha tufanye STM32 yetu kuwa kibadilishaji cha analogi hadi dijiti na kiolesura cha I 2 C ADC itachakata chaneli 8. Mdhibiti atatoa matokeo ya mabadiliko kwa Mwalimu wakati wa kusoma kutoka kwa rejista. Kwa kuwa matokeo ya ubadilishaji wa ADC ni biti 12, tunahitaji rejista 2 (baiti 2) kwa kila kituo cha ADC.

i2c_slave.h ina mipangilio:

I2CSLAVE_ADDR- anwani ya kifaa chetu;

ADC_ADDR_START- anwani ya kuanzia ya rejista ambazo zinawajibika kwa matokeo ya ubadilishaji wa ADC.

Katika faili i2c_slave.c tunavutiwa zaidi na utendaji get_i2c1_ram Na set_i2c1_ram. Kazi get_i2c1_ram ni wajibu wa kusoma data kutoka kwa rejista. Inarudi data kutoka kwa anwani maalum, ambayo hutolewa kwa Mwalimu. Kwa upande wetu, data inasomwa kutoka kwa safu i2c1_kondoo, lakini ikiwa Mwalimu anauliza anwani za rejista kutoka kwa safu iliyotengwa kwa matokeo ya ADC, basi data ya ubadilishaji wa ADC inatumwa.

get_i2c1_ram:

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

Kazi set_i2c1_ram- huandika data iliyopokelewa kutoka kwa Mwalimu kwenye rejista na anwani maalum. Kwa upande wetu, data imeandikwa tu kwa safu i2c1_kondoo. Lakini hii ni hiari. Unaweza, kwa mfano, kuongeza hundi na, wakati nambari fulani inakuja kwenye anwani fulani, fanya vitendo fulani. Kwa njia hii unaweza kutuma amri tofauti kwa microcontroller.

set_i2c1_ram:

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

Kuanzisha ni rahisi sana:

Int kuu(utupu) ( SetSysClockTo72(); ADC_DMA_init(); I2C1_Slave_init(); huku(1) ( ) )

Kwanza tunaweka mzunguko wa juu wa uendeshaji wa mtawala. Kasi ya juu inahitajika wakati ucheleweshaji wowote kwenye basi ya I 2 C unahitaji kuepukwa Kisha tunaanza operesheni ya ADC kwa kutumia DMA. KUHUSU . KUHUSU . Na hatimaye, tunaanzisha basi la I 2 C kama Mtumwa. Kama unaweza kuona, hakuna kitu ngumu.

Sasa hebu tuunganishe moduli yetu ya STM32 kwa Raspberry Pi. Hebu tuunganishe potentiometers kwenye chaneli za ADC. Na tutasoma viashiria vya ADC kutoka kwa mtawala wetu. Usisahau kwamba kwa basi ya I 2 C kufanya kazi, unahitaji kufunga vipinga vya kuvuta-up kwenye kila mstari wa basi.

Kwenye koni ya Raspberry, wacha tuangalie ikiwa kifaa chetu kinaonekana kwenye basi ya I 2 C (kuhusu hilo):

I2cdetect -y 1

Kama unaweza kuona, anwani ya kifaa 0x27, ingawa tulibainisha 0x4E. Unapopata wakati, fikiria kwa nini hii ilitokea.

Kusoma kutoka kwa rejista za kifaa cha I 2 C-Slave, tekeleza amri:

I2cget -y 1 0x27 0x00

Wapi:
0x27- anwani ya kifaa,
0x00- anwani ya usajili (0x00…0xFF).

Kuandika kwa rejista za kifaa cha I 2 C-Slave, tekeleza amri:

I2cset -y 1 0x27 0xA0 0xDD

De:
0x27- anwani ya kifaa,
0xA0- anwani ya usajili
0xDD-8-bit data (0x00…0xFF)

Amri ya awali iliandika nambari 0xDD kwenye rejista 0xA0(unaweza kuandika kwa rejista 16 za kwanza, lakini hakuna uhakika, lakini zimehifadhiwa kwa ADC). Sasa tusome:

I2cget -y 1 0x27 0xA0

Ili kurahisisha mchakato wa kusoma data ya kituo cha ADC, niliandika hati:

#!/usr/bin/env python import smbus import time bus = smbus.SMBus(1) anwani = 0x27 huku (1): ADC = (); kwa i katika masafa(0, 8): LBS = basi.read_byte_data(anwani, 0x00+i*2) MBS = basi.read_byte_data(anwani, 0x00+i*2+1) ADC[i] = MBS*256 + LBS chapisha saa ya ADC.lala(0.2)

Inapiga kura na kuonyesha matokeo ya chaneli zote 8 za ADC kwenye koni.

Kwa njia sawa, unaweza kuchanganya microcontrollers kadhaa. Mmoja wao anapaswa kuwa Mwalimu (), Mtumwa mwingine.

Nakutakia mafanikio!