Урок 23
HAL. SPI. Сдвиговый регистр 74HC595
Предыдущий урок Программирование МК STM32 Следующий урок
Сегодня мы начинаем цикл занятий по шине SPI (Serial peripheral interface).
Рассказывать про то, как данная шина работает, нет никакого смысла, так как на данном сайте вся информация об этом уже есть, достаточно посмотреть урок по данной шине для AVR.
Нам важно теперь узнать, как именно данную шину программировать в контроллерах STM32.
Мы продолжаем работать с той же платой — STM32F4-Discovery и подключим м к ней сдвиговый регистр 74HC595, хотя многие начинают изучение данной шины с акселерометра, который уже установлен на плате. Так конечно легче, но с акселерометрами мы будем работать немного позже, а пока мы слегка поломаем все стереотипы и подключим простейший сдвиговый регистр, тем более что мы его уже подключали в уроке по AVR и поэтому нам будет легче его программировать и не придётся о нем особо рассказывать.
Единственное напомню, что данный регистр в основном используется для преобразования последовательного кода, переданного по SPI в параллельный по 8-битной шине. Немного поподробнее я рассказал о шине и микросхеме в видеоверсии, ссылка на которую есть внизу на странице.
Вот схема подключения данной микросхемы к нашему контроллеру (нажмите на картинку для увеличения изображения)
Микросхема на схеме немного другая, но у нас будет именно заявленная в теме урока.
А вот так всё выглядит практически
Вместо восьми светодиодов у нас светодиодная матрица, так удобнее и компаткнее.
Вход MISO мы на контроллере не исползуем, так как нам никакой информации от микросхемы не нужно.
Проект создаём из MYLCD80, называем его SPI595. Уберем из папок файлы lcd.c и lcd.h.
Запускаем Cube. Так как проект был создан в более ранней версии Cube, то в ответ на диалог с тремя кнопками жмём «Migrate», чтобы проект наш адаптировался к новой версии.
Включим SPI3. Почему SPI3, потому что лапки на плате на удобной стороне
Включим PD0 на выход, он также находится рядом с этими ножками и потребуется нам для Chip Select
Т.к. SPI3 находится на периферии APB1 (смотрим Reference Manual), то настроим её на максимальную частоту в Clock Configuration
Посмотрим SPI3 в Configuration
Судя по технической документации на микросхему, с данной частотой она должна справиться. У неё заявлено 100 МГц.
Больше ничего не трогаем. Генерируем проект и запускаем его. Настраиваем программатор на авторезет.
Удалим из main.h объявление lcd.h.
Также удалим весь код из main.c, ну конечно не весь, а который мы создавали самы, савтогенерированный убирать не надо.
Объявим в main.c некоторые дефайны для управления ножкой Chip Select
/* USER CODE BEGIN PV */
/* Private variables ———————————————————*/
#define cs_set() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0, GPIO_PIN_RESET)
#define cs_reset() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0, GPIO_PIN_SET)
#define cs_strob() cs_reset();cs_set()
/* USER CODE END PV */
Начнем писать код в функции main() – включим выбор микросхемы
/* USER CODE BEGIN 2 */
cs_set();
Создадим буфер для данных для передачи в SPI, так как этого требует функция передачи
/* Private variables ———————————————————*/
uint8_t aTxBuffer[1]={0};
#define cs_set() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0, GPIO_PIN_RESET)
На странице 814 STM32F4_HAL_User Manual.pdf найдём функцию передачи данных в SPI. Напишем её код в проект
/* USER CODE BEGIN 2 */
cs_set();
HAL_SPI_Transmit(&hspi3,(uint8_t*)aTxBuffer, 1, 5000);
Перед вызовом данной функции положим в буфер какое-нибудь число, например 1
cs_set();
aTxBuffer[0]=0x01;
HAL_SPI_Transmit(&hspi3,(uint8_t*)aTxBuffer, 1, 5000);
Теперь нам необходим импульс на ножке cs (страница 5 даташита микросхемы)
HAL_SPI_Transmit(&hspi3,(uint8_t*)aTxBuffer, 1, 5000);
cs_strob();
Теперь давайте после небольшой задержки отправим другую цифру
cs_strob();
HAL_Delay(1000);
aTxBuffer[0]=0xFF;
HAL_SPI_Transmit(&hspi3,(uint8_t*)aTxBuffer, 1, 5000);
HAL_Delay(1000);
cs_strob();
/* USER CODE END 2 */
Прошьём контроллер, посмотрим результат
Ну и давайте теперь организуем какой-нибудь счётчик для нашей матрицы.
Объявим переменную для счётчика
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t i=0;
/* USER CODE END 1 */
Теперь давайте добавим в бесконечный сам счётчик
while (1)
{
for(i=0;i<=255;i++)
{
aTxBuffer[0]=i;
HAL_SPI_Transmit(&hspi3,(uint8_t*)aTxBuffer, 1, 5000);
cs_strob();
HAL_Delay(100);
}
/* USER CODE END WHILE */
Опять прошьём и посмотрим
На следующем уроке мы попробуем к такому же сдвиговому регистру подключить семисегментный светодиодный индикатор и поуправлять уже им.
Предыдущий урок Программирование МК STM32 Следующий урок
Техническая документация на микросхему 747HC595
Отладочную плату и сдвиговые регистры можно приобрести здесь:
Сдвиговые регистры 74HC595N 10 шт
Смотреть ВИДЕОУРОК
Добрый день!
у Вас указано CPOL=Low это правильно?
у микросхемы (согласно даташита) 74HC595 сдвиг бита и запись в выходной регистр происходят при переходе от 0 к 1 т.е. по нарастающим фронтам.
Я сильно не заморачивался. Главное, что заработало.
дело не в заморачивании, а в стабильной работе хотя бы на 50МГц
я поставил CPOL=High и пробовал 74HC595 на этой частоте и ещё использовал аппаратный NSS — завел его на строб записи в выходной регистр — он как раз формирует нарастающий фронт по окончании передачи.
CPOL=Low — правильно, вроде. В связке с битом CPOL нужно учесть бит CPHA.
Где CPHA = 1 Edge — данные с линий МOSI и MISO считываются по первому (переднему) фронту импульсов SCK.
Где CPHA = 2 Edge — данные с линий МOSI и MISO считываются по второму (заднему) фронту импульсов SCK.
А при CPOL=Low передним фронтом у нас как раз и будет переход от 0 к 1.
мне тут вылезло сообщение:
«Нельзя обращаться к сайту чаще, чем один раз в три секунды!»
… а что сайт на КР580ВМ1 сделан?
Нет, не сделал. Это борьба с атаками. Причём очень сильно помогло. Также это борьба со скачиванием контента большими порциями. А если не секрет, зачем Вам обращаться чаще чем через 3 секунды? Вы успеваете за 3 секунды всю страницу прочитать?
просто что-то листал и такое вылезло — такое ограничение показалось странным. А от скачиваний это не поможет. Могу по собственному опыту сказать, что любые уловки по ограничению скачиваний не являются препятствием для опытных специалистов.
Доброго дня!
В настройках SPI в Кубе есть вариант работы 16 бит. Как считаете, можно ли включить его, и в качестве содержимого буфера передавать два байта за один раз?
Жаль, нет возможности редактировать комментарии. Выше я написал о том случае, который рассматривается Вами дальше — два 595 чипа и четыре сегмента, для динамической индикации
Приветствую Вас.
Рассмотрели сдвиговый регистр последовательный-паралельный типа 74hc595,
но хотелось бы и обратную задачу паралельный-последовательный 74hc165, а особенно 2*8бит.
Подключение кнопок тоже дело нужное, особенно если дребезг устранить аппаратно.
Здравствуйте!
Спасибо за комментарий.
Обязательно возьму на заметку. Тема действительно интересная.
Электронщик устранял дребезг аппаратно и всегда были проблемы. Я делаю антидребезг программно — никакие наводки не мешают.
Я так понимаю, буфер представляет из себя массив из одного элемента. Это требование функции в HAL? Если да, то в случае передачи массива из n- элементов, как на обеспечить «стробирование»?
1. На схеме нет ошибки подключения 11 (CLK) ноги регистра к PC11, которая SPI3_MISO? Она не должна идти к PC10 (SPI3_CLK)?
2. То, что Вами реализовано — это не SPI из-за «строба». По идее можно реализовать в точности SPI.
1. Должна, только что эту схему собрал, минус час времени, классный урок.