የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

В የመጀመሪያው ክፍል። ከአርዱዪኖ ሱሪ ያደጉ የትርፍ ጊዜ ማሳለፊያ ኤሌክትሮኒክስ መሐንዲሶች እንዴት እና ለምን የውሂብ ሉሆችን እና ሌሎች ለማይክሮ መቆጣጠሪያ ሰነዶች ማንበብ እንዳለባቸው ለመንገር ሞከርኩ። ጽሑፉ ትልቅ ሆኖ ተገኝቷል, ስለዚህ በተለየ ጽሑፍ ውስጥ ተግባራዊ ምሳሌዎችን ለማሳየት ቃል ገባሁ. ደህና ፣ እራሱን ጫኚ ብሎ ጠራ…

ዛሬ በSTM32 (ሰማያዊ ክኒኖች) እና በ STM8 መቆጣጠሪያዎች ላይ ለብዙ ፕሮጄክቶች ቀላል ፣ ግን አስፈላጊ ተግባራትን ለመፍታት የውሂብ ሉሆችን እንዴት እንደሚጠቀሙ አሳያችኋለሁ። ሁሉም የማሳያ ፕሮጄክቶች ለምወዳቸው ኤልኢዲዎች የተሰጡ ናቸው ፣ በከፍተኛ መጠን እናበራቸዋለን ፣ ለዚህም ሁሉንም ዓይነት ሳቢ መለዋወጫዎችን መጠቀም አለብን።

ጽሑፉ እንደገና ትልቅ ሆኖ ተገኘ፣ ስለዚህ ለምቾት ሲባል ይዘቱን እየሠራሁ ነው፡-

STM32 ሰማያዊ ክኒን፡ 16 LEDs ከዲኤም634 ሾፌር ጋር
STM8፡ ስድስት PWM ፒኖችን በማዘጋጀት ላይ
STM8: 8 RGB LEDs በሶስት ፒን ላይ, ያቋርጣል

የኃላፊነት ማስተባበያ፡ እኔ መሐንዲስ አይደለሁም፣ በኤሌክትሮኒክስ ውስጥ ጥልቅ እውቀት እንዳለኝ አላስመስልም፣ ጽሑፉ እንደ እኔ ላሉ አማተሮች የታሰበ ነው። እንደውም ከሁለት አመት በፊት ራሴን እንደ ኢላማ ታዳሚ ቆጥሬ ነበር። አንድ ሰው ለማላውቀው ቺፕ የውሂብ ሉሆችን ማንበብ አስፈሪ እንዳልሆነ ቢነግረኝ፣ በይነመረብ ላይ አንዳንድ የኮድ ቁርጥራጮችን በመፈለግ እና በመቀስ እና በማጣበቂያ ፕላስተር ላይ ክራንች በመፍጠር ብዙ ጊዜ አላጠፋም ነበር።

የዚህ ጽሑፍ ትኩረት የመረጃ ሉሆች እንጂ ረቂቆች አይደሉም፣ ስለዚህ ኮዱ በጣም የተወለወለ እና ብዙ ጊዜ ክራንች ላይሆን ይችላል። ፕሮጀክቶቹ እራሳቸው በጣም ቀላል ናቸው, ምንም እንኳን ከአዲስ ቺፕ ጋር ለመጀመሪያ ጊዜ ለመተዋወቅ ተስማሚ ናቸው.

ጽሑፌ ተመሳሳይ በሆነ የትርፍ ጊዜ ማሳለፊያ ውስጥ ለመጥለቅ የሚረዳውን ሰው እንደሚረዳው ተስፋ አደርጋለሁ።

STM32

16 LEDs ከDM634 እና SPI ጋር

ሰማያዊ ክኒን (STM32F103C8T6) እና DM634 LED ነጂ በመጠቀም አነስተኛ ፕሮጀክት። በዳታ ሉሆች እገዛ ከሾፌሩ፣ ከኤስቲኤም አይኦ ወደቦች ጋር እንገናኛለን እና SPIን እናዋቅራለን።

DM634

የታይዋን ቺፕ ከ16 x 16-ቢት PWM ውጤቶች ጋር፣ በሰንሰለት ሊታሰር ይችላል። ወጣቱ ባለ 12-ቢት ሞዴል ከአገር ውስጥ ፕሮጀክት ይታወቃል የብርሃን ጥቅል. በአንድ ወቅት በዲኤም63x እና በታዋቂው TLC5940 መካከል መርጬ በዲኤም ላይ ለብዙ ምክንያቶች ተቀመጥኩ፡ 1) በ Aliexpress ላይ TLC በእርግጠኝነት የውሸት ነው፣ ይህ ግን አይደለም። 2) ዲኤም የራሱ ድግግሞሽ ጄኔሬተር ያለው ራሱን የቻለ PWM አለው; 3) በሞስኮ ውስጥ ርካሽ ሊገዛ ይችላል ፣ እና ከአሊ እሽግ አይጠብቅም። እና በእርግጥ ፣ ቺፑን እራስዎ እንዴት እንደሚቆጣጠሩ መማር አስደሳች ነበር ፣ እና ዝግጁ-የተሰራ ቤተ-መጽሐፍትን አለመጠቀም። ቺፕስ አሁን በዋናነት በ SSOP24 ፓኬጅ ውስጥ ቀርበዋል ፣ እነሱ በአስማሚው ላይ ለመሸጥ ቀላል ናቸው።

አምራቹ ታይዋን ስለሆነ፣ ዳታ ገጽ ወደ ቺፕ በቻይንኛ እንግሊዝኛ የተጻፈ ነው, ይህም ማለት አስደሳች ይሆናል. በመጀመሪያ ፒኖውትን ተመልከትፒን ግንኙነትየትኛውን እግር ማገናኘት እንዳለበት ለመረዳት እና የፒን መግለጫየፒን መግለጫ). 16 ፒን:

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
የሲንክ ዲሲ ምንጮች (ክፍት ፍሳሽ)

ዝንፍ / ክፍት-ፍሳሽ ውፅዓት - ክምችት; የመጪው ወቅታዊ ምንጭ; በነቃ ሁኔታ ውስጥ ከመሬት ጋር የተገናኘ ውጤት - LEDs ከአሽከርካሪው ጋር በካቶድ ተያይዘዋል። በኤሌክትሪክ ይህ በእርግጥ ምንም "ክፍት ፍሳሽ" የለም (ክፍት የፍሳሽ ማስወገጃ), ነገር ግን በውሂብ ሉሆች ውስጥ እንዲህ ዓይነቱ ስያሜ በፍሳሽ ሁነታ ውስጥ ለውጤቶች ብዙ ጊዜ ተገኝቷል.

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
የውጤት የአሁኑን ዋጋ ለማዘጋጀት በREXT እና GND መካከል ያሉ የውጭ መከላከያዎች

የውጤቶቹን ውስጣዊ ተቃውሞ በሚቆጣጠረው REXT ፒን እና መሬት መካከል የማጣቀሻ ተከላካይ ተጭኗል ፣ በመረጃ ወረቀቱ ገጽ 9 ላይ ያለውን ግራፍ ይመልከቱ። በዲ ኤም 634 ውስጥ፣ አጠቃላይ ድምቀቱን በማዘጋጀት ይህንን ተቃውሞ በሶፍትዌር መቆጣጠርም ይችላል።ዓለም አቀፍ ብሩህነት); በዚህ ጽሑፍ ውስጥ በዝርዝር አልገባም, እዚህ 2.2 - 3 kOhm resistor አኖራለሁ.

ቺፑን እንዴት መቆጣጠር እንደሚቻል ለመረዳት የመሣሪያውን በይነገጽ መግለጫ እንመልከት፡-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

አዎ፣ እዚህ ነው፣ ቻይንኛ እንግሊዘኛ በሁሉም ክብሩ። ይህንን ለመተርጎም ችግር አለበት ፣ ከፈለጉ ሊረዱት ይችላሉ ፣ ግን ሌላ መንገድ አለ - በውሂብ ሉህ ውስጥ በተግባራዊ ቅርብ ከሆነው TLC5940 ጋር ያለው ግንኙነት እንዴት እንደሚገለፅ ለማየት ።

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
… ውሂብን ወደ መሳሪያው ለማስገባት ሶስት ፒን ብቻ ያስፈልጋሉ። እየጨመረ ያለው የ SCLK ምልክት ውሂቡን ከ SIN ፒን ወደ ውስጣዊ መመዝገቢያ ይለውጠዋል. ሁሉም መረጃዎች ከተጫኑ በኋላ፣ አጭር ከፍተኛ XLAT ሲግናል በተከታታይ የተላለፈውን መረጃ በውስጥ መዝገቦች ውስጥ ይዘጋል። የውስጥ መዝገቦች በ XLAT ምልክት ደረጃ የሚቀሰቀሱ በሮች ናቸው። ሁሉም መረጃዎች መጀመሪያ MSB ይተላለፋሉ።

ድራክ - መቀርቀሪያ / መቀርቀሪያ / መቀርቀሪያ.
ከፍ ያለ ጫፍ የ pulse መሪ ጠርዝ ነው
MSB መጀመሪያ - በጣም አስፈላጊው (በግራ በኩል) ትንሽ ወደፊት።
ወደ ሰዓት ውሂብ - ውሂብን በቅደም ተከተል ማስተላለፍ (ቢት በቢት)።

ቃሉ መከለያ ብዙውን ጊዜ ለቺፕስ በሰነድ ውስጥ ይገኛል እና በተለያዩ መንገዶች ይተረጎማል ፣ ስለሆነም ለመረዳት እራሴን እፈቅዳለሁ።

አነስተኛ የትምህርት ፕሮግራምየ LED ነጂው በመሠረቱ የፈረቃ መመዝገቢያ ነው። "Shift" (shift) በስም - በመሣሪያው ውስጥ ያለው የውሂብ ቢት-ቢት እንቅስቃሴ: እያንዳንዱ አዲስ ወደ ውስጥ የተወጋው ሰንሰለቱን በሙሉ ከፊት ለፊት ይገፋል። በፈረቃው ወቅት የ LEDs ብልጭ ድርግም የሚል ብልጭ ድርግም የሚል ማንም ሰው ማየት ስለማይፈልግ ሂደቱ የሚካሄደው ከሰራተኞች በተለዩ በመዝጊያ መዝገቦች ውስጥ ነው።መከለያ) ቢትስ በተፈለገው ቅደም ተከተል የሚሰለፍበት የአለባበስ ክፍል ነው። ሁሉም ነገር ዝግጁ ሲሆን, መከለያው ይከፈታል እና ቢትስ ወደ ሥራ ይሄዳል, የቀደመውን ስብስብ ይተካዋል. ቃል መከለያ ለማይክሮ ሰርኩይቶች በሰነድ ውስጥ ሁል ጊዜ እንዲህ ዓይነቱን እርጥበት ያሳያል ፣ በማንኛውም ጥምረት ጥቅም ላይ ይውላል።

ስለዚህ, የውሂብ ማስተላለፍ ወደ DM634 እንደሚከተለው ይከናወናል: DAI ግብዓት በሩቅ የ LED ከፍተኛ ቢት ዋጋ ላይ ያቀናብሩ, DCK ወደ ላይ እና ወደ ታች ይጎትቱ; የ DAI ግቤትን ወደ ቀጣዩ ቢት እሴት ያቀናብሩ, DCK ይጎትቱ; እና ሁሉም ቢትስ እስኪተላለፉ ድረስተዘግቷል), ከዚያ በኋላ LAT እንጎትተዋለን. ይህ በእጅ ሊሠራ ይችላልቢት ባንግ), ነገር ግን ለዚህ በተለየ መልኩ የተሳለ የ SPI በይነገጽን መጠቀም የተሻለ ነው, ምክንያቱም በእኛ STM32 ላይ በሁለት ቅጂዎች ይቀርባል.

ሰማያዊ ታብሌት STM32F103

መግቢያ፡ የ STM32 ተቆጣጣሪዎች ከአትሜጋ328 በጣም የተወሳሰቡ ናቸው። በተመሳሳይ ጊዜ በኃይል ቁጠባ ምክንያት ሁሉም ማለት ይቻላል በጅማሬ ላይ ተሰናክለዋል ፣ እና የሰዓት ድግግሞሽ ከውስጥ ምንጭ 8 ሜኸር ነው። እንደ እድል ሆኖ፣ የኤስቲኤም ፕሮግራመሮች ቺፑን ወደ "የተሰላ" 72 ሜኸዝ የሚያመጣ ኮድ ፃፉ እና እኔ የማውቃቸው የሁሉም አይዲኢዎች ደራሲዎች በመነሻ ሂደት ውስጥ አካትተውታል ፣ ስለዚህ ሰዓት ማድረግ አያስፈልገንም (ግን ከፈለግክ ትችላለህ). ነገር ግን ተጓዳኝ ክፍሎችን ማብራት አለብዎት.

ሰነድ፡ ታዋቂው STM32F103C8T6 ቺፕ በብሉ ፒል ላይ ተጭኗል፣ ለእሱ ሁለት ጠቃሚ ሰነዶች አሉ፡

በውሂብ ሉህ ውስጥ፣ የሚከተሉትን ሊፈልጉ ይችላሉ፡-

  • Pinouts - ቺፕ pinouts - እኛ እራሳችን ሰሌዳዎችን ለመሥራት ከወሰንን;
  • የማህደረ ትውስታ ካርታ - ለተወሰነ ቺፕ የማስታወሻ ካርታ. የማጣቀሻ መመሪያው ለጠቅላላው መሾመር ካርታ አለው, በእኛ ላይ የሌሉ መዝገቦችን ይጠቅሳል.
  • የፒን ፍቺዎች ሰንጠረዥ - ዋና እና አማራጭ የፒን ተግባራትን መዘርዘር; በበይነመረብ ላይ ላለው "ሰማያዊ ክኒን" ከፒን እና ተግባሮቻቸው ዝርዝር ጋር የበለጠ ምቹ ስዕሎችን ማግኘት ይችላሉ። ስለዚህ፣ ወዲያውኑ ብሉ ፒል ፒኖውትን ጎግል አድርገን ይህን ምስል በእጃችን እናቆየዋለን፡-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
ማሳሰቢያ: ከበይነመረቡ በስዕሉ ላይ ስህተት ነበር, በአስተያየቶቹ ውስጥ ታይቷል, ለዚህም አመሰግናለሁ. ስዕሉ ተተክቷል, ነገር ግን ይህ ትምህርት ነው - መረጃን ከዳታ ሉሆች ሳይሆን መፈተሽ የተሻለ ነው.

የውሂብ ሉህውን እናስወግደዋለን, የማጣቀሻ መመሪያውን እንከፍተዋለን, ከአሁን በኋላ የምንጠቀመው እሱን ብቻ ነው.
የአሰራር ሂደት፡ ከመደበኛ ግብአት/ውፅዓት ጋር ይገናኙ፣ SPI ን ያዋቅሩ፣ አስፈላጊዎቹን ክፍሎች ያብሩ።

የግቤት ውፅዓት

በ Atmega328 ላይ፣ I/O እጅግ በጣም ቀላል ነው፣ ለዚህም ነው የ STM32 አማራጮች ብዛት ግራ የሚያጋባ የሚሆነው። አሁን እኛ መደምደሚያዎች ብቻ እንፈልጋለን ፣ ግን አራት አማራጮችም አሉ-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
የውሃ መውረጃ ውፅዓት ክፈት ፣ የግፋ-ጎትት ውፅዓት ፣ የግፊት-ጎት አማራጭ ፣ ክፍት-ማፍሰሻ አማራጭ

"ፑል-ግፋ" (መግፋት) - ከአርዱዪኖ የተለመደው ውፅዓት ፣ ፒኑ ከፍተኛ ወይም ዝቅተኛ ሊሆን ይችላል። ነገር ግን በ "ክፍት ፍሳሽ" ይነሳሉ ችግሮችምንም እንኳን በእውነቱ ሁሉም ነገር እዚህ ቀላል ቢሆንም

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
የውጤት ውቅር / ወደብ ለውጤት ሲመደብ፡/ የውጤት ቋት ሲነቃ፡/- ክፍት የፍሳሽ ሁነታ፡- “0” በውጤት መመዝገቢያ መዝገብ ውስጥ N-MOSን ያስችላል፣ “1” በውጤት መመዝገቢያ ውስጥ ወደብ በ Hi-Z ሞድ (ፒ. -MOS አልነቃም) / - የግፋ-ፑል ሁነታ: "0" በውጤት መመዝገቢያ ውስጥ N-MOS ን ያንቀሳቅሰዋል, "1" በውጤት መዝገብ ውስጥ P-MOS ን ያንቀሳቅሰዋል.

ሁሉም ክፍት የፍሳሽ ልዩነት (ክፍት የፍሳሽ ማስወገጃ) ከ "ግፋ-ጎት" (መግፋት) በመጀመሪያው ፒን ውስጥ የ HIGH ሁኔታን መውሰድ እንደማይችል ነው-አንድ ክፍል ወደ ውፅዓት መመዝገቢያ ሲፃፍ ወደ ከፍተኛ የመከላከያ ሁነታ ይሄዳል (ከፍተኛ መከላከያ, ሰላም- Z). ዜሮን በሚጽፉበት ጊዜ, በሁለቱም ሁነታዎች ውስጥ ያለው ፒን በሎጂክ እና በኤሌክትሪክ ተመሳሳይ ነው.

በተለመደው የውጤት ሁነታ, ፒኑ የውጤት መዝገቡን ይዘቶች በቀላሉ ይተረጉመዋል. በ "አማራጭ" ውስጥ በተዛማጅ ተጓዳኝ ቁጥጥር ስር ነው (9.1.4 ይመልከቱ):

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
የወደብ ቢት እንደ ተለዋጭ ተግባር ውፅዓት ከተዋቀረ የውጤት መዝገቡ ተሰናክሏል እና ፒኑ ከዳርቻው የውጤት ምልክት ጋር ይገናኛል።

የእያንዳንዱ ፒን አማራጭ ተግባር በ ውስጥ ተገልጿል ትርጓሜዎችን ይሰኩ የውሂብ ሉህ በወረደው ሥዕል ላይ ነው። ፒኑ ብዙ አማራጭ ተግባራት ካለው ምን ማድረግ እንዳለበት ሲጠየቁ መልሱ በዳታ ሉህ ውስጥ ባለው የግርጌ ማስታወሻ ይሰጣል፡-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
ብዙ ፔሪፈራሎች አንድ አይነት ፒን የሚጠቀሙ ከሆነ፣ በተለዋጭ ተግባራት መካከል ግጭት እንዳይፈጠር፣ በአንድ ጊዜ አንድ ተጓዳኝ ብቻ ጥቅም ላይ መዋል አለበት፣ ይህም የፔሪፈራል ሰዓት አንቃ ቢት (በተዛማጅ የ RCC መመዝገቢያ ውስጥ) በመጠቀም መቀየር አለበት።

በመጨረሻም፣ በውጤት ሁነታ ላይ ያሉ ፒኖች እንዲሁ የሰዓት ፍጥነት አላቸው። ይህ ሌላ የኃይል ቆጣቢ ባህሪ ነው, በእኛ ሁኔታ ከፍተኛውን ብቻ እናዘጋጃለን እና እንረሳዋለን.

ስለዚህ: እኛ SPI እየተጠቀምን ነው, ይህም ማለት ሁለት ፒን (በመረጃ እና በሰዓት ምልክት) "አማራጭ የግፋ-መጎተት ተግባር" መሆን አለበት, እና አንድ ተጨማሪ (ኤልቲ) "መደበኛ የግፊት-ፑል" መሆን አለበት. ግን ከመመደብዎ በፊት፣ ከ SPI ጋር እንነጋገር።

SPI

ሌላ ትንሽ ጠለፋ

SPI ወይም Serial Peripheral Interface (ተከታታይ ፔሪፈራል በይነገጽ) MK ከሌሎች MKs እና በአጠቃላይ ከውጭው አለም ጋር ለመግባባት ቀላል እና በጣም ውጤታማ የሆነ በይነገጽ ነው። ስለ ቻይንኛ LED ነጂ (በማጣቀሻ መመሪያ ውስጥ ክፍል 25 ይመልከቱ) የት በውስጡ ክወና መርህ, ቀደም ሲል ተገልጿል. SPI በማስተር ("ማስተር") እና በባሪያ ("ባሪያ") ሁነታዎች ውስጥ ሊሰራ ይችላል. SPI አራት መሰረታዊ ቻናሎች ያሉት ሲሆን ከነዚህም ውስጥ ሁሉም ሊሳተፉ አይችሉም፡

  • MOSI, Master Output / Slave Input: ይህ ፒን በማስተር ሁነታ ውሂብን ይልካል, እና በባሪያ ሁነታ ላይ ውሂብ ይቀበላል;
  • MISO, ዋና ግብዓት / የባሪያ ውፅዓት: በተቃራኒው, ጌታ ውስጥ ይቀበላል, ባሪያ ውስጥ ይሰጣል;
  • SCK፣ ተከታታይ ሰዓት፡ በጌታው ውስጥ ያለውን የመረጃ ስርጭት ድግግሞሽ ያዘጋጃል ወይም በባሪያው ውስጥ የሰዓት ምልክት ይቀበላል። በመሠረቱ, ድብደባዎችን ይመታል;
  • SS, Slave Select: በዚህ ቻናል, ባሪያው ከእሱ የሆነ ነገር እንደሚፈልጉ ያውቃል. በ STM32 ላይ NSS ተብሎ ይጠራል, N = አሉታዊ, ማለትም. ይህ ቻናል መሬት ካለው ተቆጣጣሪው ባሪያ ይሆናል። ከOpen Drain Output ሁነታ ጋር በደንብ ይጣመራል፣ ግን ያ ሌላ ታሪክ ነው።

ልክ እንደሌሎቹ ሁሉ፣ በ STM32 ላይ ያለው SPI በተግባራዊነት የበለፀገ ነው፣ ይህም ለመረዳት በተወሰነ ደረጃ አስቸጋሪ ያደርገዋል። ለምሳሌ, ከ SPI ጋር ብቻ ሳይሆን ከ I2S በይነገጽ ጋር ሊሰራ ይችላል, እና ገለጻዎቻቸው በሰነዶች ውስጥ ይደባለቃሉ, ትርፍውን በጊዜ መቁረጥ ያስፈልግዎታል. የእኛ ተግባር እጅግ በጣም ቀላል ነው፡ MOSI እና SCK ብቻ በመጠቀም መረጃ መስጠት ብቻ ያስፈልግዎታል። ወደ ክፍል 25.3.4 (ግማሽ-duplex ግንኙነት, ግማሽ-duplex ግንኙነት) እንሄዳለን, እዚያም እናገኛለን. 1 ሰዓት እና 1 ባለአቅጣጫ የውሂብ ሽቦ (የ1 ሰዓት ምልክት እና 1 ባለአቅጣጫ የውሂብ ዥረት)

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
በዚህ ሁነታ፣ አፕሊኬሽኑ SPIን በተላላፊ-ብቻ ወይም በተቀባዩ ብቻ ይጠቀማል። / የማስተላለፊያ-ብቻ ሁነታ ከዱፕሌክስ ሁነታ ጋር ተመሳሳይ ነው-መረብ በማስተላለፊያ ፒን ላይ ይተላለፋል (MOSI in master mode or MISO in ባሪያ ሁነታ), የመቀበያ ፒን (ኤምኤስኦ ወይም MOSI በቅደም ተከተል) እንደ መደበኛ I / O ጥቅም ላይ ሊውል ይችላል. ፒን. በዚህ አጋጣሚ አፕሊኬሽኑ የ Rx ቋቱን ችላ ማለቱ በቂ ነው (ከተነበበ ምንም የተላለፈ መረጃ አይኖርም)።

በጣም ጥሩ፣ የ MISO ፒን ነፃ ነው፣ የLAT ምልክትን ከእሱ ጋር እናገናኘው። በ STM32 ላይ በፕሮግራም ቁጥጥር ሊደረግ የሚችለውን Slave Select ጋር እንነጋገር፣ ይህም እጅግ በጣም ምቹ ነው። በክፍል 25.3.1 SPI አጠቃላይ መግለጫ ውስጥ ያለውን ተመሳሳይ ስም አንቀፅ እናነባለን፡-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
NSS ሶፍትዌር ቁጥጥር (ኤስኤስኤም = 1) / የባሪያ ምርጫ መረጃ በ SSI ቢት በ SPI_CR1 መመዝገቢያ ውስጥ ይገኛል። ውጫዊው የኤን.ኤስ.ኤስ ፒን ለሌሎች የመተግበሪያ ፍላጎቶች በነጻ ቀርቷል።

ወደ መዝጋቢዎች ለመጻፍ ጊዜው አሁን ነው. SPI2 ን ለመጠቀም ወሰንኩ ፣ የመሠረት አድራሻውን በውሂብ ሉህ ውስጥ እንፈልጋለን - በክፍል 3.3 የማህደረ ትውስታ ካርታ (የማህደረ ትውስታ ካርታ)

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

ደህና፣ እንጀምር፡-

#define _SPI2_(mem_offset) (*(volatile uint32_t *)(0x40003800 + (mem_offset)))

ክፍል 25.3.3ን “SPI in master mode በማዋቀር ላይ” በሚል ርዕስ እንከፍታለን።

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

1. በ SPI_CR2 መመዝገቢያ ውስጥ የመለያ በይነገጽ ሰዓቱን ከBR[0:1] ቢት ጋር ያዘጋጁ።

መዝገቦቹ የሚሰበሰቡት በተመሳሳዩ ስም በማጣቀሻው መመሪያ ክፍል ውስጥ ነው. የአድራሻ ለውጥ (አድራሻ ማካካሻCR1 0x00 አለው፣ በነባሪነት ሁሉም ቢት ይጸዳሉ (እሴትን ዳግም አስጀምር 0x0000):

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

የ BR ቢትስ የመቆጣጠሪያውን ሰዓት መከፋፈያ ያዘጋጃሉ, ስለዚህ SPI የሚሰራበትን ድግግሞሽ ይወስናሉ. የSTM32 ፍሪኩዌንሲው 72 ሜኸዝ ይሆናል፣ የኤልዲ ሾፌሩ በዳታ ሉህ መሠረት እስከ 25 ሜኸር በሚደርስ ድግግሞሽ ይሰራል፣ ስለዚህ በአራት መካፈል አለብን (BR[2:0] = 001)።

#define _SPI_CR1 0x00

#define BR_0        0x0008
#define BR_1        0x0010
#define BR_2        0x0020

_SPI2_ (_SPI_CR1) |= BR_0;// pclk/4

2. በመረጃ ማስተላለፍ እና ተከታታይ በይነገጽ ሰዓት መካከል ያለውን ግንኙነት ለመወሰን CPOL እና CPHA ቢት ያዘጋጁ (በገጽ 240 ላይ ያለውን ንድፍ ይመልከቱ)

እዚህ የውሂብ ሉህ እያነበብን እንጂ ስሌቶችን እየተመለከትን ስላልሆነ፣ በገጽ 704 ላይ ያለውን የCPOL እና CPHA ቢትስ ጽሑፋዊ መግለጫን ጠለቅ ብለን እንመርምር (SPI General Description):

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
የሰዓት ደረጃ እና polarity
የ SPI_CR1 መመዝገቢያ CPOL እና CPHA ቢት በመጠቀም፣ በጊዜ ሬሾዎች አራት አማራጮችን በፕሮግራም መምረጥ ትችላለህ። ምንም መረጃ በማይተላለፍበት ጊዜ CPOL (Clock Polarity) ቢት የሰዓት ምልክት ሁኔታን ይቆጣጠራል። ይህ ቢት የማስተር እና የባሪያ ሁነታዎችን ይቆጣጠራል። CPOL ዳግም ከተጀመረ፣ የ SCK ፒን በእረፍት ዝቅተኛ ነው። የ CPOL ቢት ከተቀናበረ፣ ስራ ሲፈታ የ SCK ፒን ከፍተኛ ነው።
የ CPHA (የሰዓት ደረጃ) ቢት ከተቀናበረ፣ የኤምኤስቢ ወጥመድ ስትሮብ የ SCK ሲግናል ሁለተኛ ጠርዝ ነው (CPOL ከተጸዳ መውደቅ ወይም CPOL ከተዘጋጀ ወደ ላይ ከፍ ይላል)። ውሂቡ በሁለተኛው የሰዓት ለውጥ ላይ ተዘግቷል። የ CPHA ቢት ከተጸዳ፣ ከፍተኛው የቢት ወጥመድ ስትሮብ የ SCK ሲግናል ከፍ ያለ ጠርዝ ነው (ሲፒኦል ከተዘጋጀ መውደቅ ወይም CPOL ግልጽ ከሆነ ጠርዙ ከፍ ይላል። በመጀመሪያው የሰዓት ለውጥ ላይ ውሂብ ተዘግቷል።

ይህንን እውቀት ከቀመስን በኋላ ሁለቱም ቢት ዜሮ መሆን አለባቸው ወደሚል መደምደሚያ ደርሰናል ፣ ምክንያቱም ጥቅም ላይ በማይውልበት ጊዜ የኤስኬኬ ምልክቱ ዝቅተኛ ሆኖ እንዲቆይ እና መረጃው ከፍ ባለ የልብ ምት ጠርዝ ላይ እንዲተላለፍ እንፈልጋለን (ምስል XNUMX ይመልከቱ)። እየጨመረ ጠርዝ በውሂብ ሉህ DM634)።

በነገራችን ላይ, እዚህ በመጀመሪያ በ ST የውሂብ ሉሆች ውስጥ የቃላት አወጣጥ ባህሪ አጋጥሞናል: በእነሱ ውስጥ "ትንሹን ወደ ዜሮ ዳግም አስጀምር" የሚለው ሐረግ ተጽፏል. ትንሽ እንደገና ለማስጀመርአይደለም ትንሽ ለማጽዳት, እንደ, ለምሳሌ, አትሜጋ.

3. ባለ 8-ቢት ወይም 16-ቢት ዳታ ብሎክ ቅርጸቱን ለመወሰን የዲኤፍኤፍ ቢትን ያዘጋጁ

እንደ DM16 ባለ 634-ቢት PWM ውሂብ ማስተላለፍ ላይ ላለመጨነቅ በተለይ ባለ 12-ቢት ዲኤም633ን ወስጃለሁ። ዲኤፍኤፍ አንድነቱን ማስቀመጡ ምክንያታዊ ነው፡-

#define DFF         0x0800

_SPI2_ (_SPI_CR1) |= DFF; // 16-bit mode

4. የማገጃውን ቅርጸት ለመወሰን የLSBFIRST ቢትን በ SPI_CR1 መዝገብ ውስጥ ያዋቅሩት

LSBFIRST፣ እንደ ስሙ እንደሚያመለክተው፣ መጀመሪያ በትንሹ ጉልህ በሆነ መልኩ ስርጭቱን ያዘጋጃል። ግን DM634 በመጀመሪያ MSB ውሂብ መቀበል ይፈልጋል። ስለዚህ, ዳግም ማስጀመርን እንተወዋለን.

5. በሃርድዌር ሁነታ፣ ከኤን ኤስ ኤስ ፒን ግብዓት የሚያስፈልግ ከሆነ፣ በጠቅላላው የባይት ማስተላለፊያ ቅደም ተከተል የ NSS ፒን ከፍ ያድርጉት። በ NSS ፕሮግራም ሁነታ፣ በ SPI_CR1 መመዝገቢያ ውስጥ SSM እና SSI ቢት ያዘጋጁ። የ NSS ፒን እንዲወጣ ከተፈለገ፣ የ SSOE ቢት ብቻ ነው መቀናበር የሚያስፈልገው።

ስለ NSS ሃርድዌር ሁነታ ለመርሳት SSM እና SSI ይጫኑ፡-

#define SSI         0x0100
#define SSM         0x0200

_SPI2_ (_SPI_CR1) |= SSM | SSI; //enable software control of SS, SS high

6. MSTR እና SPE ቢት መቀናበር አለባቸው (የተዘጋጁት የሚቀሩት NSS ከፍተኛ ከሆነ ብቻ ነው)

በእውነቱ፣ በእነዚህ ቢትስ የእኛን SPI እንደ ዋና መድበን እናበራዋለን፡-

#define MSTR        0x0004
#define SPE         0x0040

_SPI2_ (_SPI_CR1) |= MSTR; //SPI master
//когда все готово, включаем SPI
_SPI2_ (_SPI_CR1) |= SPE;

SPI ተዋቅሯል፣ ባይት ወደ ሾፌሩ የሚልኩ ተግባራትን ወዲያውኑ እንፃፍ። ማንበብ ይቀጥሉ 25.3.3 "SPI ን በማስተር ሞድ ማዋቀር"፡

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
የውሂብ ማስተላለፍ ትዕዛዝ
ዝውውሩ የሚጀምረው ባይት ወደ Tx ቋት ሲጻፍ ነው።
የውሂብ ባይት በ shift መዝገብ ውስጥ ተጭኗል ትይዩ ሁነታ (ከውስጥ አውቶቡስ) የመጀመሪያውን ቢት በሚተላለፍበት ጊዜ, ከዚያ በኋላ ወደ ውስጥ ይተላለፋል ወጥነት ያለው MOSI ፒን ሁነታ፣ በ CPI_CR1 መመዝገቢያ ውስጥ ባለው የ LSBFIRST ቢት ቅንብር ላይ በመመስረት መጀመሪያ ወይም የመጨረሻው ትንሽ ወደፊት። TXE ባንዲራ ከውሂብ ማስተላለፍ በኋላ ተቀናብሯል። ከTx ቋት ወደ ፈረቃ መመዝገቢያ፣ እና በCPI_CR1 መመዝገቢያ ውስጥ ያለው TXEIE ቢት ከተቀናበረ ማቋረጥ ይፈጠራል።

በኤስቲኤም መቆጣጠሪያዎች ውስጥ የ SPI ትግበራን ወደ አንድ ባህሪ ለመሳብ በትርጉሙ ውስጥ ጥቂት ቃላትን አጉልቻለሁ። በአትሜጋ፣ የTXE ባንዲራ (Tx ባዶ, Tx ባዶ ነው እና ውሂብ ለመቀበል ዝግጁ ነው) የሚዘጋጀው ሙሉውን ባይት ከተላከ በኋላ ብቻ ነው ወጣ. እና እዚህ ይህ ባንዲራ የተቀመጠው ባይት ወደ ውስጣዊ ፈረቃ መመዝገቢያ ከተጣለ በኋላ ነው. እዚያው ከሁሉም ቢትስ ጋር በተመሳሳይ ጊዜ ስለሚገፋ (በትይዩ) እና ከዚያም ውሂቡ በቅደም ተከተል ስለሚተላለፍ TXE የሚዘጋጀው ባይት ሙሉ በሙሉ ከመላኩ በፊት ነው። ይህ አስፈላጊ ነው ምክንያቱም በእኛ የ LED ነጂ, ከላኩ በኋላ የ LAT ፒን መሳብ አለብን всех ዳታ፣ ማለትም እ.ኤ.አ. የ TXE ባንዲራ ብቻ አይበቃንም.

ሌላ ባንዲራ ያስፈልገናል ማለት ነው። 25.3.7 - "የሁኔታ ባንዲራዎች" የሚለውን እንመልከት፡-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
<…>
የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
BUSY ባንዲራ
የBSY ባንዲራ ተቀናብሮ እና በሃርድዌር ጸድቷል (መጻፍ ምንም ውጤት የለውም)። የ BSY ባንዲራ የ SPI ግንኙነት ንብርብር ሁኔታን ያሳያል።
ዳግም ያስጀምረዋል፡
ዝውውሩ ሲጠናቀቅ (ከማስተር ሁነታ በስተቀር ዝውውሩ ቀጣይ ከሆነ)
SPI ሲሰናከል
የማስተር ሁነታ ስህተት ሲከሰት (MODF=1)
ስርጭቱ ቀጣይ ካልሆነ የBSY ባንዲራ በእያንዳንዱ የመረጃ ስርጭት መካከል ይጸዳል።

እሺ፣ ጠቃሚ ሆኖ ይመጣል። የTx ቋት የት እንደሚገኝ ይወቁ። ይህንን ለማድረግ "የ SPI ውሂብ መመዝገቢያ" የሚለውን ያንብቡ:

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
Bits 15:0 DR[15:0] የውሂብ መመዝገቢያ
የተቀበለው ወይም የሚተላለፍ ውሂብ.
የመረጃ መመዝገቢያ መመዝገቢያ በሁለት ቋቶች የተከፈለ ሲሆን አንደኛው ለመጻፍ (ማስተላለፊያ ቋት) እና አንድ ለማንበብ (መያዣ ተቀበል)። ለመረጃ መመዝገቢያ መመዝገቢያ ጽሁፍ ለTx ቋት ይጽፋል፣ እና ከመረጃ መዝገብ ውስጥ የተነበበ በ Rx ቋት ውስጥ ያለውን እሴት ይመልሳል።

ደህና፣ የሁኔታ መመዝገቢያ፣ TXE እና BSY ባንዲራዎች ባሉበት ቦታ፡-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

እኛ እንጽፋለን፡-

#define _SPI_DR  0x0C
#define _SPI_SR  0x08

#define BSY         0x0080
#define TXE         0x0002

void dm_shift16(uint16_t value)
{
    _SPI2_(_SPI_DR) = value; //send 2 bytes
    while (!(_SPI2_(_SPI_SR) & TXE)); //wait until they're sent
}

ደህና ፣ በ LED ነጂው የውጤቶች ብዛት መሠረት 16 ጊዜ ሁለት ባይት ማስተላለፍ ስለሚያስፈልገን እንደዚህ ያለ ነገር።

void sendLEDdata()
{
    LAT_low();
    uint8_t k = 16;
    do
    {   k--;
        dm_shift16(leds[k]);
    } while (k);

    while (_SPI2_(_SPI_SR) & BSY); // finish transmission

    LAT_pulse();
}

ግን የ LAT ፒን እንዴት መጎተት እንዳለብን ስለማናውቅ ወደ I/O እንመለስ።

ፒኖችን መድብ

በ STM32F1 ውስጥ፣ ለፒን ሁኔታ ተጠያቂ የሆኑት መዝገቦች ያልተለመዱ ናቸው። ከAtmega የበለጠ ብዙዎቹ እንዳሉ ግልጽ ነው, ነገር ግን ከሌሎች የኤስቲኤም ቺፕስ የተለዩ ናቸው. ክፍል 9.1 GPIO አጠቃላይ መግለጫ፡-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
እያንዳንዱ አጠቃላይ ዓላማ I/O ወደቦች (GPIO) ሁለት ባለ 32-ቢት የውቅር መዝገቦች (GPIOx_CRL እና GPIOx_CRH)፣ ሁለት ባለ 32-ቢት ዳታ መዝገቦች (GPIOx_IDR እና GPIOx_ODR)፣ ባለ 32-ቢት አዘጋጅ/ዳግም ማስጀመሪያ መዝገብ (GPIOx_BSRR)፣ ባለ 16-ቢት ዳግም ማስጀመር መዝገብ (GPIOx_BRR) እና 32 -ቢት የማገድ መዝገብ (GPIOx_LCKR)።

ያልተለመዱ እና ይልቁንም የማይመቹ እዚህ የመጀመሪያዎቹ ሁለት መመዝገቢያዎች ናቸው, ምክንያቱም 16 የወደቡ ፒን በ "አራት ቢት በወንድም" ቅርጸት በእነሱ ላይ ተበታትነው ይገኛሉ. እነዚያ። ፒን XNUMX እስከ XNUMX በCRL ውስጥ ናቸው፣ የተቀሩት ደግሞ በCRH ውስጥ ናቸው። በተመሳሳይ ጊዜ የቀሩት መዝገቦች የሁሉንም የወደብ ፒን ቢት በተሳካ ሁኔታ ያሟላሉ - ብዙውን ጊዜ በግማሽ ይቀራሉ "የተያዙ".

ለቀላልነት፣ ከዝርዝሩ መጨረሻ ላይ እንጀምር።

የማገጃ መዝገብ አንፈልግም።

የስብስቡ እና ዳግም ማስጀመሪያ መዝገቦች እርስ በእርሳቸው በከፊል የሚባዙ በመሆናቸው በጣም አስቂኝ ናቸው፡ ሁሉንም ነገር በ BSRR ውስጥ ብቻ መፃፍ ይችላሉ፣ የላይኞቹ 16 ቢት ፒን ወደ ዜሮ ዳግም የሚያስጀምሩት እና ዝቅተኛዎቹ ወደ 1 ይቀናበራሉ ወይም ደግሞ ይችላሉ። BRR ተጠቀም፣ የታችኛው 16 ቢት ፒኑን ብቻ ዳግም ያስጀምራል። ሁለተኛውን አማራጭ ወድጄዋለሁ። እነዚህ መዝገቦች አስፈላጊ ናቸው ምክንያቱም ለፒን የአቶሚክ መዳረሻ ይሰጣሉ፡-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
አቶሚክ መጫን ወይም ዳግም ማስጀመር
GPIOx_ODRን በቢት ደረጃ ሲያዘጋጁ ማቋረጦችን ማሰናከል አያስፈልግም፡በአንድ APB2 አቶሚክ ፃፍ ኦፕሬሽን አንድ ወይም ብዙ ቢት መቀየር ይችላሉ። ይህ የሚገኘው "1" ወደ ሴቲንግ/ዳግም ማስጀመሪያ መዝገብ (GPIOx_BSRR ወይም እንደገና ለማስጀመር ብቻ GPIOx_BRR) ለሚለውጠው ቢት በመፃፍ ነው። ሌሎች ቢት ሳይለወጡ ይቀራሉ።

የመረጃ መዝጋቢዎች በጣም የሚናገሩ ስሞች አሏቸው - IDR = ግቤት የአቅጣጫ መመዝገቢያ, የግቤት መመዝገቢያ; ODR= ዉጤት የአቅጣጫ መዝገብ, የውጤት መመዝገቢያ. አሁን ባለው ፕሮጀክት እኛ አንፈልጋቸውም።

እና በመጨረሻም መቆጣጠሪያው ይመዘገባል. የሁለተኛው SPI ፒን ማለትም PB13፣ PB14 እና PB15 ፍላጎት ስላለን ወዲያውኑ CRHን እንመለከታለን፡-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

እና ከ 20 ኛው እስከ 31 ኛ ባለው ጊዜ ውስጥ አንድ ነገር በቢት መጻፍ አስፈላጊ እንደሚሆን እናያለን.

ከላይ ካሉት ፒኖች የምንፈልገውን አስቀድመን አውቀናል፣ ስለዚህ እዚህ ያለ ቅጽበታዊ ገጽ እይታ አደርጋለሁ፣ MODE አቅጣጫውን ያዘጋጃል ይበሉ (ሁለቱም ቢት ወደ 0 ከተቀናበሩ ግቤት) እና የፒን ፍጥነት (50 ሜኸር እንፈልጋለን ፣ ማለትም)። ሁለቱም ፒን ወደ "1") ፣ እና CNF ሁነታውን ያዘጋጃል-መደበኛ “ግፋ-መጎተት” - 00 ፣ “አማራጭ” - 10. በነባሪ ፣ ከላይ እንደምናየው ፣ ሁሉም ፒኖች ከስር ሦስተኛው ቢት አላቸው ( CNF0)፣ ወደ ሁነታ ያዘጋጃቸዋል። ተንሳፋፊ ግቤት.

በዚህ ቺፕ ሌላ ነገር ለማድረግ ስላሰብኩ፣ ለቀላልነት፣ በአጠቃላይ ሁሉንም የMODE እና CNF እሴቶችን ለታችኛው እና የላይኛው የቁጥጥር መመዝገቢያ ገለጽኩ።

እንደምንም እንደዚህ

#define CNF0_0 0x00000004
#define CNF0_1 0x00000008
#define CNF1_0 0x00000040
#define CNF1_1 0x00000080
#define CNF2_0 0x00000400
#define CNF2_1 0x00000800
#define CNF3_0 0x00004000
#define CNF3_1 0x00008000
#define CNF4_0 0x00040000
#define CNF4_1 0x00080000
#define CNF5_0 0x00400000
#define CNF5_1 0x00800000
#define CNF6_0 0x04000000
#define CNF6_1 0x08000000
#define CNF7_0 0x40000000
#define CNF7_1 0x80000000
#define CNF8_0 0x00000004
#define CNF8_1 0x00000008
#define CNF9_0 0x00000040
#define CNF9_1 0x00000080
#define CNF10_0 0x00000400
#define CNF10_1 0x00000800
#define CNF11_0 0x00004000
#define CNF11_1 0x00008000
#define CNF12_0 0x00040000
#define CNF12_1 0x00080000
#define CNF13_0 0x00400000
#define CNF13_1 0x00800000
#define CNF14_0 0x04000000
#define CNF14_1 0x08000000
#define CNF15_0 0x40000000
#define CNF15_1 0x80000000

#define MODE0_0 0x00000001
#define MODE0_1 0x00000002
#define MODE1_0 0x00000010
#define MODE1_1 0x00000020
#define MODE2_0 0x00000100
#define MODE2_1 0x00000200
#define MODE3_0 0x00001000
#define MODE3_1 0x00002000
#define MODE4_0 0x00010000
#define MODE4_1 0x00020000
#define MODE5_0 0x00100000
#define MODE5_1 0x00200000
#define MODE6_0 0x01000000
#define MODE6_1 0x02000000
#define MODE7_0 0x10000000
#define MODE7_1 0x20000000
#define MODE8_0 0x00000001
#define MODE8_1 0x00000002
#define MODE9_0 0x00000010
#define MODE9_1 0x00000020
#define MODE10_0 0x00000100
#define MODE10_1 0x00000200
#define MODE11_0 0x00001000
#define MODE11_1 0x00002000
#define MODE12_0 0x00010000
#define MODE12_1 0x00020000
#define MODE13_0 0x00100000
#define MODE13_1 0x00200000
#define MODE14_0 0x01000000
#define MODE14_1 0x02000000
#define MODE15_0 0x10000000
#define MODE15_1 0x20000000

የእኛ ፒኖች ወደብ B (መሰረታዊ አድራሻ - 0x40010C00) ላይ ናቸው፣ ኮድ፡-

#define _PORTB_(mem_offset) (*(volatile uint32_t *)(0x40010C00 + (mem_offset)))

#define _BRR  0x14
#define _BSRR 0x10
#define _CRL  0x00
#define _CRH  0x04

//используем стандартный SPI2: MOSI на B15, CLK на B13
//LAT пусть будет на неиспользуемом MISO – B14

//очищаем дефолтный бит, он нам точно не нужен
_PORTB_ (_CRH) &= ~(CNF15_0 | CNF14_0 | CNF13_0 | CNF12_0);

//альтернативные функции для MOSI и SCK
_PORTB_ (_CRH) |= CNF15_1 | CNF13_1;

//50 МГц, MODE = 11
_PORTB_ (_CRH) |= MODE15_1 | MODE15_0 | MODE14_1 | MODE14_0 | MODE13_1 | MODE13_0;

እና፣ በዚህ መሰረት፣ የ BRR እና BSRR መዝገቦችን የሚያሽከረክረው ለ LAT መግለጫዎችን መጻፍ ትችላለህ፡-

/*** LAT pulse – high, then low */
#define LAT_pulse() _PORTB_(_BSRR) = (1<<14); _PORTB_(_BRR) = (1<<14)

#define LAT_low() _PORTB_(_BRR) = (1<<14)

(LAT_low በ inertia ብቻ፣ እንደምንም ሁልጊዜ ነበር፣ ለራስህ ይቆይ)

አሁን ሁሉም ነገር ጥሩ ነው, ግን አይሰራም. ይህ STM32 ስለሆነ እዚህ ኤሌክትሪክን ይቆጥባሉ, ይህም ማለት አስፈላጊውን የፔሪፈራል ሰዓትን ማብራት ያስፈልግዎታል.

ሰዓቱን ያብሩ

ሰዓቱ የሰዓት ሃላፊነት ነው, እነሱ ደግሞ ሰዓት ናቸው. እና RCC ምህጻረ ቃል አስቀድመን ልናስተውል እንችላለን። በሰነዱ ውስጥ እየፈለግን ነው-ይህ ዳግም ማስጀመር እና የሰዓት መቆጣጠሪያ (የዳግም ማስጀመር እና የሰዓት መቆጣጠሪያ) ነው።

ከላይ እንደተጠቀሰው ፣ እንደ እድል ሆኖ ፣ ከ STM የመጡ ሰዎች ለእኛ በጣም አስቸጋሪ የሆነውን የሰዓት ማዘዣ ርእሱን አደረጉ ፣ ለዚህም ብዙ አመሰግናለሁ (እንደገና አገናኝ እሰጣለሁ) የዲ ሃልት ድር ጣቢያምን ያህል ግራ እንደሚጋባ ግልጽ ለማድረግ). እኛ የምንፈልገው የዳርቻ ክሎክን ለማንቃት ኃላፊነት ያላቸው መዝጋቢዎች ብቻ ነው (የጎንዮሽ ሰዓት አንቃ ሬጅስትሮችን)። በመጀመሪያ፣ የ RCC አድራሻን እንፈልግ፣ እሱ በ"ማስታወሻ ካርድ" መጀመሪያ ላይ ነው።

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

#define _RCC_(mem_offset) (*(volatile uint32_t *)(0x40021000 + (mem_offset)))

እና ከዚያ በሠንጠረዡ ውስጥ የሆነ ነገር ለማግኘት የሚሞክሩበትን አገናኙን ጠቅ ያድርጉ ፣ ወይም ፣ በጣም በተሻለ ፣ ስለ ክፍሎቹ ስለ መዝገቦችን ጨምሮ መግለጫዎችን ይመልከቱ። መዝገቦችን ማንቃት. RCC_APB1ENR እና RCC_APB2ENR የት እናገኛለን:

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

እና በእነሱ ውስጥ ፣ በቅደም ተከተል ፣ የ SPI2 ፣ IOPB (I / O Port B) እና ተለዋጭ ተግባራትን (AFIO) መዝጋትን የሚያካትቱ ቢት።

#define _APB2ENR 0x18
#define _APB1ENR 0x1C

#define IOPBEN 0x0008
#define SPI2EN 0x4000
#define AFIOEN 0x0001

//включаем тактирование порта B и альт. функций
_RCC_(_APB2ENR) |= IOPBEN | AFIOEN;

//включаем  тактирование SPI2
_RCC_(_APB1ENR) |= SPI2EN;

የመጨረሻው ኮድ ሊገኝ ይችላል እዚህ.

ለመፈተሽ እድሉ እና ፍላጎት ካለ, DM634ን እንደዚህ እናገናኛለን-DAI ከ PB15, DCK ወደ PB13, LAT ወደ PB14. ነጂውን ከ 5 ቮልት እንመገባለን, ግቢውን ማጣመርን አይርሱ.

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

STM8 PWM

PWM በ STM8 ላይ

ይህን ጽሑፍ እያቀድኩ ሳለሁ፣ ለምሳሌ፣ ጫማ ሰሪ ያለ ቦት ጫማ እንዳይገለበጥ፣ የማላውቀውን ቺፕ በመረጃ ደብተር ብቻ በመጠቀም አንዳንድ ተግባራትን ለመቆጣጠር ለመሞከር ወሰንኩ። STM8 ለዚህ ሚና ፍጹም ነበር: በመጀመሪያ, እኔ STM8S103 ጋር አንድ ሁለት የቻይና ሰሌዳዎች ነበር, እና ሁለተኛ, በጣም ተወዳጅ አይደለም, እና ስለዚህ በኢንተርኔት ላይ ማንበብ እና መፍትሄ ለማግኘት ፈተና እነዚህ ተመሳሳይ መፍትሄዎች አለመኖር ላይ ያርፋል.

ቺፕ ደግሞ አለው ዳታ ገጽ и የማጣቀሻ መመሪያ RM0016, በመጀመሪያው ፒን እና የመመዝገቢያ አድራሻዎች, በሁለተኛው ውስጥ - ሁሉም ነገር. በአስቀያሚ አይዲኢ ውስጥ STM8 በ C ውስጥ ፕሮግራሚንግ ማድረግ ST ቪዥዋል ልማት.

Clocking እና I/O

በነባሪ, STM8 በ 2 MHz ድግግሞሽ ይሰራል, ይህ ወዲያውኑ መታረም አለበት.

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
HSI ሰዓት (ከፍተኛ ውስጣዊ)
የHSI ሰዓት ከውስጣዊ 16 MHz RC oscillator በፕሮግራም ሊሰራ የሚችል አካፋይ (1 እስከ 8) የተገኘ ነው። በሰዓት መከፋፈያ መዝገብ (CLK_CKDIVR) ተቀናብሯል።
ማሳሰቢያ፡- HSI RC oscillator 8 አካፋይ ያለው ጅምር ላይ እንደ ዋና የሰዓት ምንጭ ሆኖ ተመርጧል።

የመመዝገቢያውን አድራሻ በመረጃ ደብተር ውስጥ ፣ መግለጫውን በሪፍማን ውስጥ እናገኛለን እና መዝገቡን ማጽዳት እንዳለበት እናያለን ።

#define CLK_CKDIVR *(volatile uint8_t *)0x0050C6

CLK_CKDIVR &= ~(0x18);

PWM ን ልናስኬድ እና LEDsን ስለምናገናኝ፣ ነጥቡን እንይ፡-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

ቺፕው ትንሽ ነው, ብዙ ተግባራት በተመሳሳይ ፒን ላይ ተንጠልጥለዋል. በካሬ ቅንፎች ውስጥ ያለው “አማራጭ ተግባር” ነው፣ በ “አማራጭ ባይት” ይቀየራል።አማራጭ ባይት) - እንደ Atmega ፊውዝ ያለ ነገር። እሴቶቻቸውን በፕሮግራም መለወጥ ይችላሉ ፣ ግን አስፈላጊ አይደለም ፣ ምክንያቱም። አዲሱ ተግባር የሚነቃው ዳግም ከተጀመረ በኋላ ነው። እነዚህን ባይቶች ሊለውጠው የሚችለውን ST ቪዥዋል ፕሮግራመር (በ Visual Develop የወረደ) መጠቀም ቀላል ነው። ፒኖውት የሚያሳየው የመጀመሪያው የሰዓት ቆጣሪ CH1 እና CH2 ውጤቶች በካሬ ቅንፎች ውስጥ ተደብቀዋል። በ STVP ውስጥ AFR1 እና AFR0 ቢት ማዘጋጀት አስፈላጊ ነው, እና ሁለተኛው ደግሞ የሁለተኛ ጊዜ ቆጣሪውን CH1 ከ PD4 ወደ PC5 ያስተላልፋል.

ስለዚህ, 6 ፒን LEDs ይቆጣጠራሉ PC6, PC7 እና PC3 ለመጀመሪያ ጊዜ ቆጣሪ, PC5, PD3 እና PA3 ለሁለተኛ.

የ I/O ፒኖችን በSTM8 ላይ ማዋቀር ከSTM32 የበለጠ ቀላል እና የበለጠ ምክንያታዊ ነው።

  • አትሜጋ የሚታወቅ የመረጃ አቅጣጫ መመዝገቢያ DDR (የውሂብ አቅጣጫ ይመዝገቡ): 1 = ውፅዓት;
  • የመጀመሪያው የቁጥጥር መመዝገቢያ CR1, ሲወጣ, የግፋ-መጎተት ሁነታን (1) ወይም ክፍት ፍሳሽ (0) ያዘጋጃል; LEDs ን ከካቶዴስ ጋር ወደ ቺፕ ስላገናኘሁ፣ እዚህ ዜሮዎችን እተወዋለሁ።
  • ሁለተኛው የቁጥጥር መመዝገቢያ CR2 በሚወጣበት ጊዜ የሰዓት ፍጥነት ያዘጋጃል: 1 = 10 MHz

#define PA_DDR     *(volatile uint8_t *)0x005002
#define PA_CR2     *(volatile uint8_t *)0x005004
#define PD_DDR     *(volatile uint8_t *)0x005011
#define PD_CR2     *(volatile uint8_t *)0x005013
#define PC_DDR     *(volatile uint8_t *)0x00500C
#define PC_CR2     *(volatile uint8_t *)0x00500E

PA_DDR = (1<<3); //output
PA_CR2 |= (1<<3); //fast
PD_DDR = (1<<3); //output
PD_CR2 |= (1<<3); //fast
PC_DDR = ((1<<3) | (1<<5) | (1<<6) | (1<<7)); //output
PC_CR2 |= ((1<<3) | (1<<5) | (1<<6) | (1<<7)); //fast

PWM ቅንብር

በመጀመሪያ፣ ውሎችን እንግለጽ፡-

  • PWM ድግግሞሽ - ጊዜ ቆጣሪው የሚያልፍበት ድግግሞሽ;
  • ልሾ-ሰር ዳግም መጫን፣ AR - በራስ የተጫነ ዋጋ, ሰዓት ቆጣሪው የሚቆጠርበት (የልብ ጊዜ);
  • ክስተትን አዘምን፣ UEV - ጊዜ ቆጣሪው ወደ AR ሲቆጠር የሚከሰት ክስተት;
  • PWM የግዴታ ዑደት - ብዙውን ጊዜ "የግዴታ ዑደት" ተብሎ የሚጠራው የ PWM ግዴታ ዑደት;
  • ዋጋን ያንሱ/ያወዳድሩ - ለማንሳት / ለማነፃፀር እሴት ፣ ሰዓት ቆጣሪው እስከየትኛው ድረስ በመቁጠር የሆነ ነገር ያደርጋል (በ PWM ሁኔታ የውጤት ምልክትን ይገለበጣል);
  • ቅድመ ጭነት ዋጋ - አስቀድሞ የተጫነ ዋጋ። ዋጋ ማወዳደር የሰዓት ቆጣሪው ምልክት በሚደረግበት ጊዜ መለወጥ አይችልም፣ አለበለዚያ የ PWM ዑደት ይሰበራል። ስለዚህ፣ የሰዓት ቆጣሪው ቆጠራው መጨረሻ ላይ ሲደርስ እና ዳግም ሲጀመር አዲስ የሚተላለፉ እሴቶች ታግተው ይወጣሉ።
  • ከጫፍ ጋር የተስተካከለ и ከመሃል ጋር የተጣጣሙ ሁነታዎች - ድንበር ላይ እና መሃል ላይ አሰላለፍ, atmelovskie ጋር ተመሳሳይ ፈጣን PWM и ደረጃ-ትክክለኛ PWM.
  • OCiREF፣ የውጤት አወዳድር የማጣቀሻ ምልክት - የማመሳከሪያው የውጤት ምልክት, በእውነቱ, በተዛማጅ ፒን ላይ በ PWM ሁነታ ላይ የሚታየው.

ቀደም ሲል ከፒንዮውት ግልጽ ሆኖ, ሁለት ጊዜ ቆጣሪዎች PWM ችሎታዎች አላቸው - የመጀመሪያው እና ሁለተኛ. ሁለቱም 16-ቢት ናቸው, የመጀመሪያው ብዙ ተጨማሪ ባህሪያት አሉት (በተለይ, ሁለቱንም ወደላይ እና ወደ ታች ሊቆጥረው ይችላል). ሁለታችንም በተመሳሳይ መንገድ እንዲሰሩ እንፈልጋለን, ስለዚህ በእሱ ውስጥ ያልሆነን ነገር በአጋጣሚ ላለመጠቀም, በግልጽ ድሃ በሆነው ሁለተኛ ለመጀመር ወሰንኩ. አንዳንድ ችግር የሁሉም የሰዓት ቆጣሪዎች የ PWM ተግባር መግለጫ በማጣቀሻ መመሪያው ውስጥ ስለ መጀመሪያው ጊዜ ቆጣሪ (17.5.7 PWM ሁነታ) በምዕራፍ ውስጥ ነው ፣ ስለሆነም ሁል ጊዜ በሰነዱ ውስጥ ወደ ኋላ እና ወደ ፊት መዝለል አለብዎት።

PWM በ STM8 ላይ ከአትሜጋ PWM ጠቃሚ ጥቅም አለው፡-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
PWM ከጫፍ አሰላለፍ ጋር
የመለያ ውቅር ከስር ወደ ላይ
በ TIM_CR1 መመዝገቢያ ውስጥ ያለው DIR ቢት ግልጽ ከሆነ መቁጠር ገቢር ይሆናል።
ለምሳሌ:
ምሳሌው የመጀመሪያውን PWM ሁነታ ይጠቀማል. የPWM ማመሳከሪያ ሲግናል OCIREF እስከ TIM1_CNT <TIM1_CCRI ድረስ ይያዛል። አለበለዚያ ዝቅተኛ ደረጃ ይወስዳል. በ TIM1_CCRi መመዝገቢያ ውስጥ የሚወዳደረው ዋጋ ከአውቶ ጫኝ ዋጋ (TIM1_ARR መመዝገቢያ) የበለጠ ከሆነ፣ የ OciREF ምልክቱ በ1 ላይ ተይዟል። የንፅፅር ዋጋው 0 ከሆነ፣ OciREF በዜሮ ተይዟል።...

STM8 ጊዜ ቆጣሪ ክስተት አዘምን መጀመሪያ ቼኮች ዋጋ ማወዳደር, እና ከዚያ በኋላ ብቻ የማጣቀሻ ምልክት ይፈጥራል. በአትሜጋ፣ ሰዓት ቆጣሪው መጀመሪያ ይንቀጠቀጣል፣ ከዚያም ያወዳድራል፣ በውጤቱም፣ መቼ compare value == 0 ውጤቱ በሆነ መንገድ መታከም ያለበት መርፌ ነው (ለምሳሌ ፣ አመክንዮውን በፕሮግራም በመገልበጥ)።

ስለዚህ እኛ ማድረግ የምንፈልገው: 8-ቢት PWM (AR == 255), ከታች ወደ ላይ በመቁጠር, በድንበሩ ላይ ማስተካከል. አምፖሎቹ ከቺፑ ጋር በካቶድ የተገናኙ በመሆናቸው PWM 0 (LED on) እስከ ድረስ ማውጣት አለበት። ዋጋ ማወዳደር እና 1 በኋላ.

ስለ አንዳንዶቹ ቀደም ብለን አንብበናል። PWM ሁኔታስለዚህ የዚህን ሐረግ ማመሳከሪያ (18.6.8 - TIMx_CCMR1) በመፈለግ የተፈለገውን የሁለተኛ ጊዜ ቆጣሪ መዝገብ እናገኛለን።

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
110: የመጀመሪያው PWM ሁነታ - ከታች ወደ ላይ ሲቆጠር የመጀመሪያው ሰርጥ እስከ TIMx_CNT < TIMx_CCR1 ድረስ ይሰራል። አለበለዚያ የመጀመሪያው ቻናል እንቅስቃሴ-አልባ ነው። [በተጨማሪ በሰነዱ ውስጥ፣ የተሳሳተ ቅጂ-መለጠፍ ከ ሰዓት ቆጣሪ 1] 111፡ ሁለተኛ PWM ሁነታ - ከታች ወደ ላይ ሲቆጠር የመጀመሪያው ቻናል እስከ TIMx_CNT < TIMx_CCR1 ድረስ አይሰራም። አለበለዚያ የመጀመሪያው ቻናል ገባሪ ነው።

ኤልኢዲዎች ከ MK ጋር ከካቶድ ጋር የተገናኙ ስለሆኑ, ሁለተኛው ሁነታ እኛን ይስማማናል (የመጀመሪያው ደግሞ, ግን ይህን እስካሁን አናውቅም).

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
ቢት 3 OC1PE፡ ቅድመ ጭነት ውፅዓት 1ን አንቃ
0፡ ቅድመ ጭነት ምዝገባ በTIMx_CCR1 ተሰናክሏል። በማንኛውም ጊዜ ለTIMx_CCR1 መጻፍ ይችላሉ። አዲሱ ዋጋ ወዲያውኑ ይሰራል.
1፡ ቀድሞ ጫን ምዝገባ TIMx_CCR1 ነቅቷል። ክዋኔዎች ማንበብ/መፃፍ የቅድመ ጭነት መመዝገቢያውን ይድረሱ። ቀድሞ የተጫነው የTIMx_CCR1 እሴት በእያንዳንዱ የዝማኔ ክስተት በጥላ መመዝገቢያ ውስጥ ይጫናል።
*ማስታወሻ፡ የPWM ሁነታ በትክክል እንዲሰራ የቅድመ ጭነት መዝገቦች መንቃት አለባቸው። ይህ በነጠላ ሲግናል ሁነታ አማራጭ ነው (የ OPM ቢት በTIMx_CR1 መመዝገቢያ ውስጥ ተቀምጧል)።

እሺ፣ ለሁለተኛ ጊዜ ቆጣሪው ሶስት ቻናሎች የሚፈልጉትን ሁሉ ያብሩ፡

#define TIM2_CCMR1 *(volatile uint8_t *)0x005307
#define TIM2_CCMR2 *(volatile uint8_t *)0x005308
#define TIM2_CCMR3 *(volatile uint8_t *)0x005309

#define PWM_MODE2   0x70 //PWM mode 2, 0b01110000
#define OCxPE       0x08 //preload enable

TIM2_CCMR1 = (PWM_MODE2 | OCxPE);
TIM2_CCMR2 = (PWM_MODE2 | OCxPE);
TIM2_CCMR3 = (PWM_MODE2 | OCxPE);

AR ሁለት ስምንት-ቢት መዝገቦችን ያቀፈ ነው ፣ ሁሉም ነገር እዚህ ቀላል ነው-

#define TIM2_ARRH  *(volatile uint8_t *)0x00530F
#define TIM2_ARRL  *(volatile uint8_t *)0x005310

TIM2_ARRH = 0;
TIM2_ARRL = 255;

ሁለተኛው ሰዓት ቆጣሪ ከታች ወደ ላይ ብቻ መቁጠር ይችላል, በድንበሩ ላይ ማስተካከል, ምንም መለወጥ አያስፈልግም. ፍሪኩዌንሲ መከፋፈሉን ለምሳሌ ወደ 256 ያዋቅሩት። ለሁለተኛ ጊዜ ቆጣሪ፣ አካፋዩ በ TIM2_PSCR መመዝገቢያ ውስጥ ተዘጋጅቷል እና የሁለት ኃይል ነው።

#define TIM2_PSCR  *(volatile uint8_t *)0x00530E

TIM2_PSCR = 8;

መደምደሚያዎችን እና ሁለተኛውን ሰዓት ቆጣሪ እራሱ ለማብራት ይቀራል. የመጀመሪያው ተግባር በመመዝገቢያዎች ይፈታል ማንሳት/አወዳድር አንቃ: ከመካከላቸው ሁለቱ አሉ ፣ ሶስት ቻናሎች ባልተመጣጠነ ሁኔታ በእነሱ ላይ ተበታትነዋል። እዚህ ደግሞ የምልክት ምልክትን ፖላሪቲ መለወጥ እንደሚቻል መማር እንችላለን, ማለትም. በመርህ ደረጃ፣ PWM Mode 1 ጥቅም ላይ ሊውል ይችላል፡-

#define TIM2_CCER1 *(volatile uint8_t *)0x00530A
#define TIM2_CCER2 *(volatile uint8_t *)0x00530B

#define CC1E  (1<<0) // CCER1
#define CC2E  (1<<4) // CCER1
#define CC3E  (1<<0) // CCER2

TIM2_CCER1 = (CC1E | CC2E);
TIM2_CCER2 = CC3E;

እና በመጨረሻ፣ ሰዓት ቆጣሪውን በቲኤምኤክስ_CR1 መመዝገቢያ ውስጥ እንጀምራለን፡-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

#define TIM2_CR1   *(volatile uint8_t *)0x005300

TIM2_CR1 |= 1;

ትክክለኛዎቹን እሴቶች ለማነፃፀር ጊዜ ቆጣሪውን የሚያልፍ አናሎግ ራይት () ቀላል አናሎግ እንፃፍ። መዝገቦቹ ሊገመቱ ይችላሉ መዝገቦችን ያንሱ/ያወዳድሩለእያንዳንዱ ቻናል ሁለቱ አሉ፡ ዝቅተኛው 8 ቢት TIM2_CCRxL እና ከፍተኛ ቢት በ TIM2_CCRxH። ባለ 8-ቢት PWM ስለጀመርን ዝቅተኛውን ቢት ብቻ መጻፍ በቂ ነው፡-

#define TIM2_CCR1L *(volatile uint8_t *)0x005312
#define TIM2_CCR2L *(volatile uint8_t *)0x005314
#define TIM2_CCR3L *(volatile uint8_t *)0x005316

void setRGBled(uint8_t r, uint8_t g, uint8_t b)
{
    TIM2_CCR1L = r;
    TIM2_CCR2L = g;
    TIM2_CCR3L = b;
}

በትኩረት የሚከታተለው አንባቢ 100% መሙላትን መስጠት ያልቻልን ትንሽ ጉድለት ያለበት PWM እንዳለን ያስተውላል (በከፍተኛው 255 እሴት ምልክቱ በአንድ የሰዓት ቆጣሪ ዑደት ይገለበጣል)። ለ LEDs, ይህ ሚና አይጫወትም, እና በትኩረት የሚከታተለው አንባቢ እንዴት ማስተካከል እንዳለበት አስቀድሞ ይገምታል.

PWM በሁለተኛው ሰዓት ቆጣሪ ላይ ይሰራል, ወደ መጀመሪያው ይሂዱ.

የመጀመሪያው ሰዓት ቆጣሪ በተመሳሳዩ መዝገቦች ውስጥ በትክክል ተመሳሳይ ቢት አለው (በሁለተኛው ሰዓት ቆጣሪ ውስጥ “የተያዙት” የቀሩት ቢት በመጀመሪያዎቹ ለሁሉም ዓይነት የላቁ ነገሮች በንቃት ጥቅም ላይ ይውላሉ)። ስለዚህ, በመረጃ ደብተር ውስጥ ተመሳሳይ የመመዝገቢያ አድራሻዎችን ማግኘት እና ኮዱን መቅዳት በቂ ነው. መልካም, የድግግሞሽ መከፋፈያውን ዋጋ ይለውጡ, ምክንያቱም. የመጀመሪያው ሰዓት ቆጣሪ የሁለት ኃይል ሳይሆን ትክክለኛ ባለ 16-ቢት ዋጋ በሁለት መዝገቦች ውስጥ ማግኘት ይፈልጋል Prescaler ከፍተኛ и ዝቅ ያለ. ሁሉንም ነገር እናደርጋለን እና ... የመጀመሪያው ሰዓት ቆጣሪ አይሰራም. ምንድነው ችግሩ?

ችግሩን ለመፍታት ብቸኛው መንገድ ስለ ሰዓት ቆጣሪ 1 የቁጥጥር መመዝገቢያዎች ሙሉውን ክፍል በመመልከት ነው, ሁለተኛው ሰዓት ቆጣሪ የሌለውን እየፈለግን ነው. አደለም 17.7.30 መስበር መዝገብ (TIM1_BKR)ትንሽ እንደዚህ ባለበት ቦታ፡-

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
ዋናውን ውጤት አንቃ

#define TIM1_BKR   *(volatile uint8_t *)0x00526D

TIM1_BKR = (1<<7);

ለአሁኑ ያ ብቻ ነው፣ ኮዱ እዚያ.

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

STM8 Multiplex

በ STM8 ላይ ማባዛት።

ሶስተኛው ሚኒ-ፕሮጀክት ስምንት RGB LEDs ከሁለተኛው የሰዓት ቆጣሪ ጋር በPWM ሁነታ ማገናኘት እና የተለያዩ ቀለሞችን እንዲያሳዩ ማድረግ ነው። እሱ በጣም ፣ በጣም በፍጥነት LEDs ን ካበሩ እና ካጠፉት ያለማቋረጥ እንደሚመስሉን በሚመስለው የ LED multiplexing ጽንሰ-ሀሳብ ላይ የተመሠረተ ነው።የእይታ ጽናት, የእይታ ግንዛቤ መጨናነቅ). አንዴ አደረግሁ በ arduino ላይ እንደዚህ ያለ ነገር.

የሥራው ስልተ ቀመር ይህንን ይመስላል

  • የመጀመሪያውን RGB LED anode ተገናኝቷል;
  • አብርቶታል, አስፈላጊዎቹን ምልክቶች ለካቶዶች መስጠት;
  • የ PWM ዑደት መጨረሻ ላይ ጠብቋል;
  • የሁለተኛው RGB LED anode ተገናኝቷል;
  • አበራው...

እንግዲህ ወዘተ. እርግጥ ነው, ለቆንጆ ሥራ, የአኖድ ግንኙነት እና የ LED "ማብራት" በአንድ ጊዜ እንዲከሰት ያስፈልጋል. ደህና, ከሞላ ጎደል. በማንኛውም ሁኔታ በሁለተኛው የሰዓት ቆጣሪ ሶስት ሰርጦች ውስጥ እሴቶችን የሚያወጣ ኮድ መጻፍ ፣ UEV ሲደርስ መለወጥ እና በተመሳሳይ ጊዜ አሁን ያለውን የ RGB LED መለወጥ አለብን።

የ LED መቀየር አውቶማቲክ ስለሆነ የአቋራጭ ተቆጣጣሪው መረጃ የሚቀበልበት "የቪዲዮ ማህደረ ትውስታ" መፍጠር ያስፈልግዎታል. ይህ ቀላል ድርድር ነው፡-

uint8_t colors[8][3];

የአንድ የተወሰነ LED ቀለም ለመቀየር አስፈላጊዎቹን እሴቶች በዚህ ድርድር ላይ መጻፍ በቂ ይሆናል። እና ተለዋዋጭው ለንቁ LED ቁጥር ተጠያቂ ይሆናል

uint8_t cnt;

ዴሙክስ

ለትክክለኛው ማባዛት ፣ በሚያስደንቅ ሁኔታ ፣ CD74HC238 demultiplexer እንፈልጋለን። Demultiplexer - ኦፕሬተሩን በሃርድዌር ውስጥ የሚተገበር ቺፕ <<. በሶስት የግብዓት ፒን (ቢት 0፣ 1 እና 2) ባለ ሶስት ቢት ቁጥር X እንመግበዋለን፣ በምላሹም የውጤት ቁጥሩን ያነቃል።1<<X). የተቀሩት የቺፑ ግብዓቶች ሙሉውን ንድፍ ለመለካት ጥቅም ላይ ይውላሉ. ይህንን ቺፕ የምንፈልገው የማይክሮ መቆጣጠሪያውን የተያዙትን ፒኖች ብዛት ለመቀነስ ብቻ ሳይሆን ለደህንነትም ጭምር - በተቻለ መጠን ብዙ ኤልኢዲዎችን እንዳያበሩ እና ኤምኬን እንዳያቃጥሉ ነው። ቺፕው አንድ ሳንቲም ያስከፍላል, ሁልጊዜም በቤት ውስጥ የመጀመሪያ እርዳታ መስጫ ውስጥ መቀመጥ አለበት.

CD74HC238 ቮልቴጅን ወደ ተፈላጊው የኤልኢዲ አኖድ የማቅረብ ሃላፊነት አለበት። ሙሉ ባለ ብዙ ብዜት በ P-MOSFET በኩል ቮልቴጅን ወደ አምድ ያቀርባል, ነገር ግን በዚህ ማሳያ ውስጥ በቀጥታ ሊሠራ ይችላል, ምክንያቱም እንደሚለው, 20mA ይጎትታል ፍጹም ከፍተኛ ደረጃዎች በውሂብ ሉህ ውስጥ. ከ የውሂብ ሉህ CD74HC238 እኛ ፒኖውት እና ይህ የማጭበርበሪያ ወረቀት እንፈልጋለን

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
H = ከፍተኛ የቮልቴጅ ደረጃ, L = ዝቅተኛ የቮልቴጅ ደረጃ, X - ግድ የለሽ

E2 እና E1ን ከመሬት ጋር፣ E3፣ A0፣ A1 እና A3 ከፒዲ5፣ ፒሲ3፣ ፒሲ4 እና ፒሲ5 ከ STM8 ጋር እናገናኛለን። ከላይ ያለው ሰንጠረዥ ዝቅተኛ እና ከፍተኛ ደረጃዎችን ስለሚይዝ እነዚህን ፒኖች እንደ ፑል-ፑል ፒን አድርገን እናዘጋጃቸዋለን.

PWM

PWM በሁለተኛው ሰዓት ቆጣሪ ላይ እንደ ቀድሞው ታሪክ በተመሳሳይ መንገድ ተዋቅሯል ፣ ከሁለት ልዩነቶች ጋር።

በመጀመሪያ መቆራረጡን ማንቃት አለብን ክስተት አዘምን (UEV) የነቃውን LED ለመቀየር ተግባርን የሚጠራው። ይህ ቢት በመለወጥ ነው አዘምን መቋረጥ አንቃ በንግግር ስም መዝገብ ውስጥ

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
መመዝገቢያ አንቃን አቋርጥ

#define TIM2_IER   *(volatile uint8_t *)0x005303

//enable interrupt
TIM2_IER = 1;

ሁለተኛው ልዩነት እንደ multiplexing እንዲህ ያለ ክስተት ጋር የተያያዘ ነው ghosting - የዲያዶስ ጥገኛ ፍካት። በእኛ ሁኔታ፣ ሰዓት ቆጣሪው በ UEV ላይ መስተጓጎል በመፍጠሩ፣ መዥገሯን ስለሚቀጥል፣ እና የአቋራጭ ተቆጣጣሪው ሰዓት ቆጣሪው ወደ ውጤቶቹ አንድ ነገር መጻፍ ከመጀመሩ በፊት ኤልኢዱን ለመቀየር ጊዜ ስለሌለው ሊመስል ይችላል። ይህንን ለመዋጋት አመክንዮውን መገልበጥ ያስፈልግዎታል (0 = ከፍተኛ ብሩህነት ፣ 255 = ምንም አልበራም) እና ከፍተኛ የግዴታ ዑደት እሴቶችን አይፍቀዱ። እነዚያ። ከ UEV በኋላ ኤልኢዲዎች ለአንድ PWM ዑደት ሙሉ በሙሉ መጥፋታቸውን ያረጋግጡ።

ፖላሪቲውን ይቀይሩ;

//set polarity 
    TIM2_CCER1 |= (CC1P | CC2P);
    TIM2_CCER2 |= CC3P;

r, g እና bን ወደ 255 ከማቀናበር ይቆጠቡ እና ሲጠቀሙ እነሱን መገልበጥዎን ያስታውሱ።

ይቋረጣል

የማቋረጥ ዋናው ነገር በተወሰኑ ሁኔታዎች ውስጥ ቺፕ ዋናውን ፕሮግራም መተግበሩን ያቆማል እና አንዳንድ ውጫዊ ተግባራትን ይጠራል. ማቋረጦች የሚከሰቱት በጊዜ ቆጣሪው ጨምሮ በውጫዊ ወይም ውስጣዊ ተጽእኖዎች ምክንያት ነው.

በ ST Visual Develop ውስጥ ፕሮጀክትን ለመጀመሪያ ጊዜ ስንፈጥር፣ ከ main.c ሚስጥራዊ ፋይል ያለው መስኮት አግኝተናል stm8_interrupt_vector.cበፕሮጀክቱ ውስጥ በራስ-ሰር ተካቷል. በዚህ ፋይል ውስጥ ከእያንዳንዱ መቆራረጥ ጋር አንድ ተግባር ተያይዟል። NonHandledInterrupt. ተግባራችንን ከተፈለገው መቆራረጥ ጋር ማሰር አለብን።

የውሂብ ሉህ የምንፈልገውን የምናገኝበት የአቋራጭ ቬክተር ሠንጠረዥ አለው፡

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8
13 TIM2 ዝማኔ/ትርፍ
14 TIM2 ቀረጻ/አወዳድር

LED ን በ UEV መቀየር አለብን፣ ስለዚህ #13 ማቋረጥ ያስፈልጋል።

በዚህ መሠረት, በመጀመሪያ, በፋይሉ ውስጥ stm8_interrupt_vector.c ለማቋረጥ ቁጥር 13 (IRQ13) ኃላፊነት የተሰጠውን ተግባር ስም በነባሪ ወደ እኛ ቀይር፡-

{0x82, TIM2_Overflow}, /* irq13 */

በሁለተኛ ደረጃ, ፋይል መፍጠር አለብን main.h እንደዚህ ያለ ይዘት

#ifndef __MAIN_H
#define __MAIN_H

@far @interrupt void TIM2_Overflow (void);
#endif

እና በመጨረሻም ይህንን ተግባር በእርስዎ ውስጥ ይፃፉ main.c:

@far @interrupt void TIM2_Overflow (void)
{
    PD_ODR &= ~(1<<5); // вырубаем демультиплексор
    PC_ODR = (cnt<<3); // записываем в демультиплексор новое значение
    PD_ODR |= (1<<5); // включаем демультиплексор

    TIM2_SR1 = 0; // сбрасываем флаг Update Interrupt Pending

    cnt++; 
    cnt &= 7; // двигаем счетчик LED

    TIM2_CCR1L = ~colors[cnt][0]; // передаем в буфер инвертированные значения
    TIM2_CCR2L = ~colors[cnt][1]; // для следующего цикла ШИМ
    TIM2_CCR3L = ~colors[cnt][2]; // 

    return;
}

ማቋረጦችን ለማንቃት ይቀራል። ይህ የሚከናወነው በአሰባሳቢ ትእዛዝ ነው። rim - እሱን መፈለግ አለብዎት የፕሮግራም አወጣጥ መመሪያ:

//enable interrupts
_asm("rim");

ሌላ ሰብሳቢ መመሪያ- sim - ማቋረጦችን ያጠፋል. አዲስ እሴቶች ወደ "የቪዲዮ ማህደረ ትውስታ" በሚጻፉበት ጊዜ ማሰናከል አለባቸው ስለዚህ በአሳዛኝ ጊዜ የተፈጠረው መቋረጥ ድርድርን እንዳያበላሽ።

ሁሉም ኮድ - በ Github ላይ.

የውሂብ ሉሆችን አንብብ 2፡ SPI በSTM32; PWM፣ የሰዓት ቆጣሪዎች እና ማቋረጥ በSTM8

ይህ ጽሑፍ ቢያንስ አንድ ሰው ጠቃሚ ከሆነ እኔ በከንቱ አልጻፍኩም። ለአስተያየቶች እና አስተያየቶች ደስ ይለኛል, ሁሉንም ለመመለስ እሞክራለሁ.

ምንጭ: hab.com

አስተያየት ያክሉ