ايران ويج

نسخه‌ی کامل: راهنمايي براي پروتكل SPI
شما در حال مشاهده‌ی نسخه‌ی متنی این صفحه می‌باشید. مشاهده‌ی نسخه‌ی کامل با قالب بندی مناسب.
صفحه‌ها: 1 2
سلام به همگي ...

دوستان ارتباط SPI بين 2 ميكرو چجورياست ... ؟
help بسكام و كتاب 1nafar رو خوندم ...
كليات كار رو مي دونم ،‌اما ...
سؤال ها رو يكي يكي بپرسم يا .... ؟ Biggrin
بين 2 ميكرو ارتباطي برقرار مي شه اما چيزي نيست كه مي خوام... !

--------------------
1-فرض كنيد يك متغير string رو مي خواهيد از mic1 به mic2 بفرستيد و mic2 اون رو روي LCD نشون بده .
كد اش چجور مي شه ؟!

2-بخش config براي SPI براي ميكروي Slave بايد تا چه حد نوشته بشه ؟
بنظرم نبايد نيازي به ديوايد كلاك و ... باشه ديگه ... ، چون كلاك رو از مستر براي اسليو مي فرستيم.

3-امكانات SPI سخت افزاري و نرم افزاري فرق مي كنه ؟
وقتي به صورت نرم افزاري پيكربندي مي كنيم ، مستر و اسليو چطور مشخص مي شه ؟
مي شه نرم افزاري رو به سخت افزاري هم وصلش كرد ؟
---------------------

فعلا همينا ...
خودمم دارم روش كار مي كنم.
پيشاپيش ممنونم از جواب هاتون.

يا علي.
به دیتاشیت مراجعه کنید کامل توضیح داده.
در حالت سخت افزاری میکرو داده رو به سخت افزار میده و تا انتهای ارسال CPU آزاد برای انجام پردازش ها و کار های دیگه. و این عالی ترین حالت استفاده است. (مناسب برای کار با LCD ها- دوربین ها و ... .
در حالت نرم افزاری برای ارسال تک تک بیت ها CPU مشغول صفر و یک کردن پایه های معرفی شده SPI هست. تازه ممکن بیت خطا توسط slave ارسال شود و در تمام زمان CPU اشغال میشه. تازه به خاطر انجام مراحل نرم افزاری سرعتش ارتباط هم خیلی محدود.
ممنون از راهنماييتون ...
قسمت SPI رو از روي datasheet هم خوندم. بعضي قسمت هاش حسابي آدم رو گيج ميكنه ...
من يه اشتباه كوچولو داشتم كه رفعش كردم درست شد.
الان SPI سخت افزاري جواب ميده ، گرچه در ارسال اطلاعات بعضي حروف كمي خراب مي شن ، اما تونستم حساسيتش رو كم كنم ( ورودي mic1 يه keypad هست ، در قسمت config kbd كمي ويژگي اضاف كردم ، با آزمون و خطا ... الان بهترهه)
-------------------------------------
حالا اومدم سراغ SPI نرم افزاري .
ارتباط نرم افزاري به سخت افزاري جواب نداد .
بعد اومدم سراغ نرم افزاري به نرم افزاري ، بازم جواب نداد !!!
جالبه كه اصلا سر دستور spiin نمي ايسته ( از وقتي كه نرم افزاري پيكر بنديش كردم !!! )
بنظرتون مشكل از كجاست ؟

-----------------------------------
راستي اين نكته هم بگم ( البته احتمالا خودتون مي دونيد )
در mic اي كه قرار slave باشه ، براي پيكربندي SPI در حد كد زير تعريف كنيد كافيه ...
کد:
Config Spi = Hard
----------------------------------
پس منتظر راهنماييتون هستم ، هر چي به ذهنم مي رسيد براي پيكر بنديه نرم افزاري انجام دادم اما جواب نداد ...
پيشاپيش ممنون از راهنمايي هاتون ...

موفق باشيد.
يا علي.

اول از همه اینکه پیشنهاد میکنم بری سراغ کامپایلر های C
خیلی وقت که با bascom کار نکردم.
اما کد رو قرار بدی چک می کنم.
خيلي ممنون از لطفتون.
كمي codevision خوندم ، تصميم گرفتم bascom رو كامل كنم و بعد برم سراغ codevision ...
اين ارتباط بين يك atmega8 هست كه بهش يك keypad وصل شده.
طرف ديگه هم يك atmega32 هست كه lcd بهش وصل شده .

atmega 8 :
کد:
$regfile = "m8def.dat"
$crystal = 8000000
Config Kbd = Portd , Debounce = 25 , Delay = 130
'Config Portb.2 = Output
'Portb.2 = 1
'Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = High , Phase = 0 , Clockrate = 4 , Noss = 1
Config Spi = Soft , Din = Pinc.2 , Dout = Pinc.1 , Ss = Pinb.2 , Clock = Pinc.3 , Spiin = 0
Spiinit
Dim Gt As Byte , Ad As Byte , Sd(14) As String * 16
Sd(14) = " It is Zero     "
Sd(1) = " Hello Mamad    "
Sd(2) = " Hello Ali    "
Sd(3) = " Hello Reza   "
Sd(4) = " Hello Mom      "
Sd(5) = " Hello Everybody"
Sd(6) = " Hello Dad      "
Sd(7) = " You entered 9  "
Sd(8) = " You entered 9  "
Sd(9) = " 123            "
Sd(10) = " 234            "
Sd(11) = " 345            "
Sd(12) = " 456            "
Sd(13) = " It is SW SPI ! "
Do
Main:
Ad = Getkbd()
If Ad > 15 Then
Goto Main
End If
Gt = Lookup(ad , Dta)
'Portb.2 = 0
Select Case Gt
Case 0 : Spiout Sd(14) , 16
Case 1 : Spiout Sd(1) , 16
Case 2 : Spiout Sd(1) , 16
Case 3 : Spiout Sd(1) , 16
Case 4 : Spiout Sd(2) , 16
Case 5 : Spiout Sd(3) , 16
Case 6 : Spiout Sd(4) , 16
Case 7 : Spiout Sd(5) , 16
Case 8 : Spiout Sd(6) , 16
Case 9 : Spiout Sd(7) , 16
Case 10 : Spiout Sd(8) , 16
Case 11 : Spiout Sd(9) , 16
Case 12 : Spiout Sd(10) , 16
Case 13 : Spiout Sd(11) , 16
Case 14 : Spiout Sd(12) , 16
Case 15 : Spiout Sd(13) , 16
End Select
'Portb.2 = 1
'Waitms 500
Loop
End
Dta:
Data 14 , 13 , 12 , 11 , 10 , 9 , 6 , 3 , 0 , 8 , 5 , 2 , 15 , 7 , 4 , 1

atmega32 :

کد:
$regfile = "m32def.dat"
$crystal = 8000000
Config Portb.1 = Output
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portc.4 , Rs = Portc.5
Config Spi = Soft , Din = Pina.6 , Dout = Pina.5 , Ss = Pina.4 , Clock = Pina.7 , Spiin = 0
'Config Spi = Hard
', Interrupt = Off , Data Order = Msb , Master = No, Polarity = High , Phase = 0 , Clockrate = 4 , Noss = 0
Spiinit
Dim Recv As String * 16 , Llcd As String * 16
Dim A As Byte
Main:
Llcd = " Waitting ... "
Cls
Lcd Llcd
Do
Set Portb.1
Waitms 100
Spiin Recv , 16
Waitms 10
Cls
Locate 1 , 1
Lcd Recv
Reset Portb.1
Waitms 100
Loop
End

فقط دقت كنيد كه اول بعضي از كد ها اين علامت هست ( ' ) كه دستور رو comment مي كنه ...
بازم ممنون.
این که گفتم با کامپایلر های C کار کنیم نه این که بیسیک بد باشه
من خودم علاقه مند به VB هستم اما Bascom استاندارد نیست کامپایلر زنده ای نیست مشکلات و باگ های که داره رو برطرف نمی کنند و فقط کتاب خونه هاش تغییر میدن، تازه نه از نوع متن باز.

هر دو مستر بودند که!. یعنی هر دو پالس می دادند و CLKpin در حالت تصادف میرفت.
در بیسکام وقتی spi رو روی HARd قرار میدیم یک پارامتر داریم به نام master=yes/no.
اما وقتی روی وضعیت SOFT قرار بدیم SPI فقط MASTER هست. برای استفاده Slave باید کتابخونه spislave.lbx رو فراخوانی کنیم.
کد مربوط به MEGA32 که slave بود رو تصحیح کردم. فقط فراموش نکنی پایه SS به PD.0 که همون INT0 هست انتقال پیدا کرده.
البته دیتا به صورت بایت به بایت دریافت میشه که باید اون رو دوباره کنار هم بچینی و به string تبدیل کنی

کد:
$regfile = "m32def.dat"
$crystal = 8000000
Config Portb.1 = Output
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portc.4 , Rs = Portc.5
' Config Spi = Soft , Din = Pina.6 , Dout = Pina.5 , Ss = Pina.4 , Clock = Pina.7 , Spiin = 0
'Config Spi = Hard
', Interrupt = Off , Data Order = Msb , Master = No, Polarity = High , Phase = 0 , Clockrate = 4 , Noss = 0
'Spiinit

Const _softslavespi_port = Porta
Const _softslavespi_pin = Pina
Const _softslavespi_ddr = Ddra
Const _softslavespi_clock = 7
Const _softslavespi_miso = 5
Const _softslavespi_mosi = 6
'Const _softslavespi_ss = 4
$lib "spislave.lbx"
$external _spisoftslave
On Int0 Isr_sspi Nosave
Enable Int0
Config Int0 = Falling
Enable Interrupts



Dim Recv As String * 16 , Llcd As String * 16
Dim Recv_byte As Byte
Dim A As Byte
Main:
Llcd = " Waitting ... "
Cls
Lcd Llcd
Do
Set Portb.1
Waitms 100
'Spiin Recv , 16


Dim _ssspdr As Byte                                         ' this is out SPI SLAVE SPDR register
Dim _ssspif As Bit                                          ' SPI interrupt revceive bit
If _ssspif = 1 Then
   Recv_byte = _ssspdr
   Reset _ssspif
End If


Waitms 10
Cls : Locate 1 , 1
Lcd Recv_byte
Reset Portb.1
Waitms 100
Loop
End
بله متوجهم ، تركيب هر دو از نظر من انتخاب خوبيه ...
اما اين مدتي كه با بسكام كار مي كنم ، فقط فهميدم كه نمي تونه با PWM ، timer0 درست كنه ، اما در codevision مي شه همچين كاري كرد.
باگ ديگه اي ازش نديدم . اگر چندتا نقطه ضعف ديگه كه بهش برخورد كرديد رو بگيد خيلي ممنون مي شم.

------------------
در مورد SPI نرم افزاري ...
واقعا ممنون . خيلي كمكم كرديد.
اتفاقا ديدم كه در help گفته بود فقط براي حالت مستر هست و اون كتاب خونه ي slave هم به چشم خورد كه گفته بود براي ميكرو هايي هست كه spi interface رو ندارن ، اما نتونستم خوب دركش كنم.
الان تقريبا فهميدم چي به چيه ...
فقط به خاطر پايه ي int0/ss ، مجبور شدم بقيه ي پايه ها رو هم بيارم روي portd ، چون غير از اين جواب نمي داد.

همونطور كه ديديد ، سعي داشتم يك رشته رو انتقال بدم. با آزمون خطا هايي كه انجام دادم به حرفتون رسيدم.
فقط 1byte مي شه انتقال داد. نوع داده ي گيرنده رو string كردم و ديدم همونطور كه گفتيد ، فقط 1 حرف كه معادل 1 byte هست رو مي گيره ...
با اين اوصاف ، اگر از سمت فرستنده 16 بايت بفرستيم ( 16 بايت فرستاده مي شه يا 1 بايت ؟ )
در سمت گيرنده كه 1 بايت گرفته مي شه ، باقيه داده ها از بين مي ره ؟
چطور داده ها رو بگيرم ؟ كه بعدا بخوام پشت سر هم بذارم و يكيشون كنم.
مي شه از فرستنده ، به جاي يك ارسال ،‌ به صورت متوالي ارسال داشته باشيم ، مثلا براي ارسال 4 بايت و داده از نوع string ، دستور Spiout رو 4 بار پشت سر هم بنويسيم ( با اعمال تاخير بينشون ) و هر بار يك بايت رو ( 1 حرف رو بذاريم ) ، بعد در سمت گيرنده در يك آرايه داده ها رو بگيريم و با هم جمع كنيم كه يكي بشن. ( با دستور if و ... )
اما فكر مي كنم مشكلات timing اين وسط پيش بياد و بعضي داده ها از بين برن.
روش درست همينه يا روش بهتري هم هست ؟

بازم ممنون از لطفتون.
یادمه قبلا برای تنظیم wdog اشکال داشت. از همه بدتر این که در اعمال ریاضی و منطق نمیشه بیش از یک عمل در خط انجام داد.
_____________
پروتکل spi رو میتونی بصورت نرم افزاری خودت بسازی خیلی سخت نیست. یعنی تابع ای درست کنی برای ارسال و دریافت. که نیازی به اینتراپت هم نباشد.
پیشنهاد من اینه که به صورت سخت افزاری راه بندازیش. (با توجه به نوشته های بالا)سخت افزاری به سخت افزاری رو آزمایش نکرده بودی. کار کردن باهاش راحت تر هم هست.
اما اگر به پایه های مورد نظر احتیاج داری. برای دریافت نرم افزاری می تونی از یه حلقه استفاده کنی. که 16 بایت رو دریافت کنه و بعد اطلاعات رو نمایش بده. یا میتونی یک کد عددی رو به عنوان پایان جمله تعریف کنی که اطلاعات رو در بافر ذخیره کنه و با دریافت کد پایان جمله بافر رو به برنامه تحویل بده.
------------------------ ويرايش ----------------------
بازم ممنون. چرا . اول از همه سخت افزاري رو امتحان كردم ،‌اون راحت بود و واقعا عالي بود . بابت ايده ها هم ممنونم. موقعي كه مطالب زير رو مي نوشتم هنوز پستتوت رو نديده بودم :d
به هر حال خيلي ممنون از راهنماييتون ، به كارم كلي سرعت داديد.

----------------------------------------------------------

خوب دوستان ، روشي رو كه بالا گفتم امتحان كردم و جواب داد و داده اي از بين نرفت .
ايده هاي ديگه اي هم ميشه بكار برد . به هر حال منتظر دوستان هستيم براي دادن بهترين ايده ...
ايده ي اين كار اينطور بوده كه ، از atmega8 كه مستر هست قراره رشته اي به طول 2 ( اندازه ي 2 بايت ) به atmega32 كه slave هست منتقل بشه. به ميكروي مستر يك keypad وصل هست كه هر عددي كه ازش زده بشه باعث مي شه 2بايت داده به ميكروي slave ارسال بشه . ميكروي slave هم داده اي رو كه ميگيره روي LCD نشون مي ده.
براي ارتباط سخت افزاري مشكلي نيست و ارتباط راحت بر قرار ميشه ، اما براي نرم افزاري احتياج به كد نويسي بيشتري داره ... .
در سمت گيرنده ، گيرنده منتظر مي مونه تا " " رو دريافت كنه كه بفهمه قرارهه رشته ها رو به ترتيب بگيرهه ...
براي ارسال هم در سمت مستر ، به محض زده شدن كليد. اول " " و به ترتيب بقيه ارسال مي شوند.
در سمت گيرنده از " " صرف نظر مي شه و باقيه اطلاعات رو كه طول برابري دارن پشت سر هم مي چينه و يكپارچه مي كنه ... .
اگر طول داده متفاوت بود مي شه يك شرط هم براي آخر رشته گذاشت ( مثل null )

--------------------
برنامه اي رو كه پايين مي ذارم كامل هست و كار مي كنه . بعضي قسمت ها با علامت ( ' ) هستن ، اونايي كه مربوط به spi سخت افزاريه ، خوب ارتباط رو از طريق سخت افزاري امكان پذير مي كنه .
اما به اين فرمي كه الان مي ذارم براي ارتباط نرم افزاريه و 100% جواب مي ده. البته مي تونه خيلي خيلي بهينه تر باشه ...
اين فقط يه پروژه براي ياد گيريه پروتكل SPI بودهه ...
به اين دليل مي ذارم كه نتيجه و چكيده ي اين تاپيك مشخص بشه و كسايي كه همچين مشكلي دارن ،‌راحت برطرف كنن.

-------------------------------
atmega8 :
کد:
$regfile = "m8def.dat"
$crystal = 8000000
Config Kbd = Portd , Debounce = 25 , Delay = 130
'Config Portb.2 = Output
'Portb.2 = 1
'Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = High , Phase = 0 , Clockrate = 4 , Noss = 1
Config Spi = Soft , Din = Pinc.2 , Dout = Pinc.1 , Ss = Pinb.2 , Clock = Pinc.3
Spiinit
Dim Gt As Byte , Ad As Byte , Sd(15) As String * 1
Sd(14) = "Z"
Sd(1) = "H"
Sd(2) = "e"
Sd(3) = "l"
Sd(4) = "o"
Sd(5) = "E"
Sd(6) = "D"
Sd(7) = "Y"
Sd(8) = "n"
Sd(9) = "1"
Sd(10) = "2"
Sd(11) = "3"
Sd(12) = "4"
Sd(13) = "t"
Sd(15) = " "
Do
Main:
Ad = Getkbd()
If Ad > 15 Then
Goto Main
End If
Gt = Lookup(ad , Dta)
'Portb.2 = 0
Spiout Sd(15) , 1
Waitms 10
Select Case Gt
Case 0 : Spiout Sd(14) , 1
Waitms 10 : Spiout Sd(6) , 1
  Waitms 10 : Spiout Sd(4) , 1
Case 1 : Spiout Sd(1) , 1
Waitms 10 : Spiout Sd(2) , 1
  Waitms 10 : Spiout Sd(3) , 1
Case 2 : Spiout Sd(1) , 1
Waitms 10 : Spiout Sd(3) , 1
  Waitms 10 : Spiout Sd(3) , 1
Case 3 : Spiout Sd(1) , 1
Waitms 10 : Spiout Sd(4) , 1
  Waitms 10 : Spiout Sd(5) , 1
Case 4 : Spiout Sd(2) , 1
Waitms 10 : Spiout Sd(5) , 1 : Waitms 10
  Spiout Sd(6) , 1
Case 5 : Spiout Sd(3) , 1
Waitms 10 : Spiout Sd(7) , 1 : Waitms 10
  Spiout Sd(8) , 1
Case 6 : Spiout Sd(4) , 1
Waitms 10 : Spiout Sd(9) , 1 : Waitms 10
  Spiout Sd(10) , 1
Case 7 : Spiout Sd(5) , 1
Waitms 10 : Spiout Sd(10) , 1 : Waitms 10
  Spiout Sd(11) , 1
Case 8 : Spiout Sd(6) , 1
Waitms 10 : Spiout Sd(11) , 1 : Waitms 10
  Spiout Sd(12) , 1
Case 9 : Spiout Sd(7) , 1
Waitms 10 : Spiout Sd(12) , 1 : Waitms 10
  Spiout Sd(13) , 1
Case 10 : Spiout Sd(8) , 1
Waitms 10 : Spiout Sd(13) , 1 : Waitms 10
  Spiout Sd(14) , 1
Case 11 : Spiout Sd(9) , 1
Waitms 10 : Spiout Sd(2) , 1 : Waitms 10
  Spiout Sd(14) , 1
Case 12 : Spiout Sd(10) , 1
Waitms 10 : Spiout Sd(3) , 1 : Waitms 10
  Spiout Sd(13) , 1
Case 13 : Spiout Sd(11) , 1
Waitms 10 : Spiout Sd(4) , 1 : Waitms 10
  Spiout Sd(12) , 1
Case 14 : Spiout Sd(12) , 1
Waitms 10 : Spiout Sd(5) , 1 : Waitms 10
  Spiout Sd(11) , 1
Case 15 : Spiout Sd(13) , 1
Waitms 10 : Spiout Sd(6) , 1 : Waitms 10
  Spiout Sd(9) , 1
End Select
'Portb.2 = 1
'Waitms 500
Loop
End
Dta:
Data 14 , 13 , 12 , 11 , 10 , 9 , 6 , 3 , 0 , 8 , 5 , 2 , 15 , 7 , 4 , 1

atmega32 :
اون portb.1 يه led هست كه براي چك كردن رفت و اومد برنامه گذاشته بودم ...
کد:
$regfile = "m32def.dat"
$crystal = 8000000
Config Portb.1 = Output
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portc.4 , Rs = Portc.5
' Config Spi = Soft , Din = Pina.6 , Dout = Pina.5 , Ss = Pina.4 , Clock = Pina.7 , Spiin = 0
'Config Spi = Hard
', Interrupt = Off , Data Order = Msb , Master = No, Polarity = High , Phase = 0 , Clockrate = 4 , Noss = 0
'Spiinit
Const _softslavespi_port = Portd
Const _softslavespi_pin = Pind
Const _softslavespi_ddr = Ddrd
Const _softslavespi_clock = 6
Const _softslavespi_miso = 5
Const _softslavespi_mosi = 4
Const _softslavespi_ss = 2
$lib "spislave.lbx"
$external _spisoftslave
On Int0 Isr_sspi Nosave
Enable Int0
Config Int0 = Falling
Enable Interrupts
Dim Recv(3) As String * 1 , Llcd As String * 16 , Rrecv As String * 3
Dim Recv_byte As Byte , B As Byte
Dim A As Byte
A = 1
Main:
Llcd = " Waitting ... "
Cls
Lcd Llcd
Do
Set Portb.1
Waitms 100
'Spiin Recv , 16
Dim _ssspdr As String * 1                                   ' this is out SPI SLAVE SPDR register
Dim _ssspif As Bit                                          ' SPI interrupt revceive bit
If _ssspif = 1 Then
'   Recv_byte = _ssspdr
Recv(a) = _ssspdr
If Recv(a) = " " Then
A = 0
End If
A = A + 1
If A = 3 Then
A = 1
B = 1
End If
   Reset _ssspif
End If
If B = 1 Then
Rrecv = Recv(1) + Recv(2) + Recv(3)
Waitms 10
Cls : Locate 1 , 1
'Lcd Recv_byte
Lcd Rrecv
Reset Portb.1
Waitms 100
B = 0
End If
Loop
End

خوب به كمك Pardazesh-Gar ، دوست عزيز ، پرونده ي پروتكل SPI هم بسته شد.
حركت بعدي 1wire يا I2C هست.

موفق باشيد.
يا علي.
سلام به همه.
اقا من دارم با پرتکل spi کار میکنم اخه لازمش دارم واسه راه اندازی ماژول NRF 24 l 01
خب:
میکرو مستر واسه ارسال دیتا به اسلیو مشکلی نداره و میکرو اسلیو هم وقفه spi فعال کردم راحت هر چی بیاد دریافت میکنه
تا اینجا مشکلی نداشتم
حالا میخوام برنامه رو گسترش بدم ارتباط دوطرفه باشه یعنی این میکرو ک چیزی فرستاد اونم در جواب مقداری رو برگردونه
اومدم وقفه spi مستر رو هم فعال کردم تا زمانی که اسلیو چیزی بفرسته این راحت بگیردش
اما کلا قاطی کرده
به محض فعال کردن وقفه سراسری دیگه چیزی ارسال نمیشه چ برسه ب دریافت
تا زمانی که disable spi مینویسم ،که اونم فقط ارسال به اسلیو درست میشه نمیشه چیزی دریافت کنم
لطفا کمک کنید
سلام
برنامه ای رو که واسش نوشتید پیوست کنید بررسی بشه
صفحه‌ها: 1 2