spi.txt 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. Аппаратный вариант
  2. Для работы с аппаратным SPI его нужно сначала, естественно,
  3. инициализировать. Посмотрим, как это будет выглядеть для ATmega8535 (а
  4. также для многих других МК того же класса, например, ATmega8515, ATmega16 и
  5. пр., у которых выводы аппаратного SPI совпадают с интерфейсом
  6. SPI-программирования и занимают старшие 4 бита порта В). Заодно
  7. инициализируем и вывод для управления "выбором кристалла" — в большинстве
  8. случаев он в интерфейсе SPI играет важную роль (например, микросхемы
  9. памяти, которые мы рассмотрим далее, высокий уровень на этом выводе, кроме
  10. всего прочего, устанавливает в состояние с низким потреблением). Часто для
  11. этого выбирают вывод /SS, который в режиме "мастера" не задействован (не
  12. забудем, что его нужно сконфигурировать на выход!), но мы для разнообразия
  13. выберем вывод РВО — часто требуется управлять несколькими устройствами,
  14. одного вывода /SS тогда все равно недостаточно, и младшие биты порта В,
  15. идущие подряд, оказываются более удобными (листинг 11.1).
  16. [ Листинг 11.1 ]
  17. .equ CS = РВ0
  18. .equ MOSI = PB5
  19. .equ MISO = РВ6
  20. .equ SCK = PB7 ;разряды порта В, используемые интерфейсом SPL.
  21. Листинг 11.2 иллюстрирует инициализацию в режиме 0 ("мастер", DORD = 0 —
  22. старший бит первым, SPR1 и SPR0 = 0 — скорость fрез/4).
  23. [ Листинг 11.2 ]
  24. ldi temp,(1<<SPE)+(1<<MSTR)
  25. out SPCR,temp
  26. ldi temp,(l<<SCK)+(1<<MOSI)+(1<<CS)+(1<<PB4)
  27. out DDRB,temp ;SCK,MOSI,CS, SS - выходы
  28. sbi PORTB,CS ;сразу устанавливаем в 1
  29. Листинг 11.3 иллюстрирует инициализацию в режиме 3 ("мастер", DORD = 0 —
  30. старший бит первым, SPR1 и SPR0 = 0 — скорость fрез/4).
  31. [ Листинг 11.3 ]
  32. ldi temp, (1«SPE) + (1«MSTR) + (1«CP0L) + (1«CPHA)
  33. out SPCR,temp
  34. ldi temp, (1«SCK) + (1«M0SI) + (1«CS) + (1«PB4)
  35. >out DDRB,temp ;SCK,MOSI,CS, SS - выходы
  36. ser temp ;0xFF
  37. out PORTB,temp ;PB7..0 — высокий уровень, весь порт В
  38. Процедура записи-чтения тогда будет выглядеть очень просто (листинг 11.4).
  39. [ Листинг 11.4 ]
  40. WR_spi: ;запись-чтение SPI, в temp данные на входе и на выходе
  41. out SPDR,temp ; начать передачу
  42. wait_spi:
  43. sbis SPSR,SPIF ; ожидаем конца передачи
  44. rjmp wait_spi
  45. in temp,SPDR ; чтение данных
  46. ret
  47. При работе с большинством устройств через SPI, к сожалению, этой простой
  48. процедурой дело не ограничивается — чаще всего требуется, по крайней мере,
  49. вовремя правильно установить "выбор кристалла", причем иногда (если
  50. интерфейс у ведомого устройства недостаточно скоростной) с формированием
  51. искусственных задержек и прочими сложностями, сильно загромождающими
  52. программу.
  53. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  54. Программный вариант
  55. Программный вариант процедур чтения-записи более громоздок, но зато
  56. позволяет задействовать любые удобные выводы портов МК (в том числе и
  57. таких, которые вообще аппаратного SPI не имеют) и не требует особой
  58. инициализации, кроме формирования направления работы соответствующих
  59. выводов. Листинг 11.5 иллюстрирует, как будет выглядеть чтение-запись в
  60. варианте, соответствующем режиму 0.
  61. [ Листинг 11,5 ]
  62. .equ CS = 0 ; выводы PortB
  63. .equ MOSI = 1
  64. .equ MISO = 2
  65. .equ SCK = 3
  66. ...
  67. ; инициализация SPI
  68. ; установка MOSI, SCK, CS на выход
  69. ldi temp,(1<<CS)|(1<<MOSI)|(1<<SCK)
  70. out DDRB,temp
  71. cbi PORTB,SCK
  72. cbi PORTB,MOSI
  73. sbi PORTB,CS
  74. ...
  75. ;чтение-запись
  76. RW_spi: ;запись/чтение через SPI. посылаемый байт в data_out,
  77. ; принимаемый в data_in
  78. cli ; на случай, если в программе есть длинные
  79. ; прерывания, иначе можно удалить
  80. ldi temp,8 ; счетчик бит
  81. clr data_in
  82. spi_Loop:
  83. lsl data_out ;старший бит в перенос
  84. brcc put_0 ; если в переносе 0 — перейти
  85. sbi PORTB,mosi
  86. nop ; задержка на один такт
  87. rjmp r_bit
  88. put_0:
  89. cbi PORTB,mosi
  90. nop ; задержка на один такт
  91. r_bit:
  92. sbi PORTB,sck ; выдали строб и подождали
  93. nop ; задержка на один такт
  94. sbic PINB,miso ; читаем бит с miso
  95. rjmp r1_bit
  96. clc ; если 0 — сбросим перенос
  97. rjmp rend_bit
  98. r1_bit:
  99. sec ; если 1 — установим перенос
  100. rend_bit:
  101. rol data_in ; перенос во входной байт
  102. cbi PORTB,sck ; выдали строб и подождали
  103. nop
  104. dec temp
  105. brne spi_loop
  106. sei ; если команды cli нет, то тоже можно удалить
  107. ret
  108. При тактовой частоте МК 4 МГц такая процедура обеспечит скорость передачи
  109. порядка 0,5 МГц. Пустые операции (пор) нужны, чтобы сформировать задержку
  110. (-250 не при 4 МГц) между формированием данных на линиях MISO и MOSI и
  111. моментом их чтения (перепадом на SCK). Если быстродействие ведомого
  112. позволяет, то эти операции можно убрать.