Режим ведущего: различия между версиями
Андрей (обсуждение | вклад) Нет описания правки |
Андрей (обсуждение | вклад) |
||
Строка 174: | Строка 174: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
}}У ведомого все настройки (CLKPhase, CLKPolarity, DataSize ) должны совпадать с настройками ведущего. | }} | ||
У ведомого все настройки (CLKPhase, CLKPolarity, DataSize ) должны совпадать с настройками ведущего. | |||
Вывод логического анализатора можно видеть на рисунке. Теперь сигнал CS становится неактивным только после каждого третьего байта. | Вывод логического анализатора можно видеть на рисунке. Теперь сигнал CS становится неактивным только после каждого третьего байта. | ||
=== Ручной режим управления сигналом выбора ведомого CS === | ===Ручной режим управления сигналом выбора ведомого CS=== | ||
Если требуется управлять сигналом CS вручную, например для того чтобы сигнал CS не устанавливался в неактивное состояние между посылками, то следует задать настройке ManualCS значение SPI_MANUALCS_ON. Функция SPI0_Init будет выглядеть так: | |||
{{#spoiler:show=Развернуть код|hide=Свернуть код| | |||
<syntaxhighlight lang="c" line="1"> | |||
static void SPI0_Init(void) | |||
{ | |||
hspi0.Instance = SPI_0; | |||
/* Режим SPI */ | |||
hspi0.Init.SPI_Mode = HAL_SPI_MODE_MASTER; | |||
/* Настройки */ | |||
hspi0.Init.BaudRateDiv = SPI_BAUDRATE_DIV64; | |||
hspi0.Init.CLKPhase = SPI_PHASE_ON; | |||
hspi0.Init.CLKPolarity = SPI_POLARITY_LOW; | |||
hspi0.Init.Decoder = SPI_DECODER_NONE; | |||
hspi0.Init.DataSize = SPI_DATASIZE_24BITS; | |||
/* Настройки для ведущего */ | |||
hspi0.Init.ManualCS = SPI_MANUALCS_ON; /* Настройки ручного режима управления сигналом CS */ | |||
HAL_SPI_Init(&hspi0); | |||
} | |||
</syntaxhighlight> | |||
}} | |||
Управлять состоянием вывода CS можно с помощью функций HAL_SPI_CS_Enable и HAL_SPI_CS_Disable. Перед использованием HAL_SPI_CS_Enable следует включить модуль SPI функцией HAL_SPI_Enable. В конце передачи модуль SPI выключается функцией HAL_SPI_Disable. | |||
Функция main: | |||
{{#spoiler:show=Развернуть код|hide=Свернуть код| | |||
<syntaxhighlight lang="c" line="1"> | |||
int main() | |||
{ | |||
SystemClock_Config(); | |||
UART_Init(UART_0, 3333, UART_CONTROL1_TE_M | UART_CONTROL1_M_8BIT_M, 0, 0); | |||
SPI0_Init(); | |||
uint8_t master_output[] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xB0, 0xB1}; | |||
uint8_t master_input[sizeof(master_output)]; | |||
while (1) | |||
{ | |||
/* Начало передачи в ручном режиме управления CS */ | |||
HAL_SPI_Enable(&hspi0); | |||
HAL_SPI_CS_Enable(&hspi0, SPI_CS_0); | |||
/* Передача и прием данных */ | |||
HAL_SPI_Exchange(&hspi0, master_output, master_input, sizeof(master_output)); | |||
/* Конец передачи в ручном режиме управления CS */ | |||
if(hspi0.Init.ManualCS == SPI_MANUALCS_ON) | |||
HAL_SPI_CS_Disable(&hspi0); | |||
HAL_SPI_Disable(&hspi0); | |||
/* Вывод принятый данных и обнуление массива master_input */ | |||
for(uint32_t i = 0; i < sizeof(master_input); i++) | |||
{ | |||
xprintf("master_input[%d] = 0x%02x\n", i, master_input[i]); | |||
master_input[i] = 0; | |||
} | |||
for (volatile int i = 0; i < 1000000; i++); | |||
} | |||
} | |||
</syntaxhighlight> | |||
}} |
Версия от 09:26, 16 марта 2023
В примере будет проведена настройка SPI в режиме ведущего. Ведущий будет читать и передавать 12 байт.
Работа с конфигуратором (В разработке)
Для начала настроем в конфигураторе тактирование mik32, например, от внешнего кварца 32МГц. Затем настроем делители шины. Так как SPI тактируется от шины APB_P_CLK, то зададим делитель AHB_DIV и APB_P_CLK. В данном примере оставим делитель по умолчанию. В итоге вкладка с тактированием должна выглядеть так:
(Картинка тактирования из конфигуратора. В работе)
Затем перейдем к настройке самого SPI. Для этого откроем вкладку интерфейсы, выберем SPI и зададим режим работы ведомый. После этого появятся несколько настроек.
Зададим им следующие значения:
- Делитель частоты - 64;
- Фаза тактового сигнала - Тактовая частота неактивна вне слова;
- Полярность тактового сигнала вне слова - Тактовый сигнал удерживается на низком уровне;
- Длина передаваемой посылки - 8 бит;
- Периферийный декодер - Выбор 1 из 4 устройств;
- Режим управления сигналом выбора ведомого - Автоматический;
- Ведомый - Устройство 1.
В итоге настройки SPI в конфигураторе должны выглядеть как на рисунке.
Нажимаем кнопку сохранения и генерации. В итоге у нас появится проект для PlatformIo. Далее работа идет в visual studio code.
Использование библиотеки HAL_SPI
В сгенерированном проекте в файле main.c должна быть функция SPI0_Init, в которой будут заданы настройки для SPI. Выглядит она так:
Кроме этого в функции SystemClock_Config приведены настройки для тактирования. Убедитесь что в PeriphClkInit.PMClockAPB_P присутствует PM_CLOCK_SPI_0_M. Сама функция должна выглядеть примерно так:
Для демонстрации вывода текста в PeriphClkInit.PMClockAPB_P присутствует PM_CLOCK_UART_0_M. У вас его может не быть так как UART нужно включить отдельно. Для этого нужно подключить библиотеки uart_lib и xprintf:
Для инициализации UART в функции main после функции тактирования SystemClock_Config следует написать
UART_Init(UART_0, 3333, UART_CONTROL1_TE_M | UART_CONTROL1_M_8BIT_M, 0, 0);
Скорость UART задается делителем во втором аргументе функции. При такой записи скорость будет 9600 бод.
В начале main.c можно видеть объявление структуры с набором настроек для SPI, которую использует функция инициализации SPI0_Init.
Создадим в функции main массив master_output, который будет содержать в себе 12 байт, которые ведущий будет отправлять ведомому. Создадим массив maser_input такого же размера как и master_output для принятых данных.
Обмен данными запускается с помощью функции HAL_SPI_Exchange. Функция main
В данном примере ведущая плата общается по SPI с ведомой платой, которая запрограммирована как в примере "Режим ведомого". То есть ведомый должен прислать ведущему следующий набор байт: 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xC0, 0xC1. Для того чтобы в этом убедиться, ведущий пишет принятые байты в UART. Вывод UART изображен на рисунке.
Вывод логического анализатора можно видеть на рисунке.
Посылка больше 8 бит
На выводе логического анализатора можно видеть как сигнал CS переходит в неактивное состояние между байтами. Для того чтобы этого не было можно увеличить число байт в посылке. Есть 4 вида длины посылки:
- 8 бит (1 байт);
- 16 бит (2 байта);
- 24 бита (3 байта);
- 32 бита (4 байта).
Будем отправлять наши 12 байт посылками по 3 байта. Для этого в функции SPI0_Init нужно присвоить значение настройке DataSize равное SPI_DATASIZE_24BITS. Функция SPI0_Init
У ведомого все настройки (CLKPhase, CLKPolarity, DataSize ) должны совпадать с настройками ведущего.
Вывод логического анализатора можно видеть на рисунке. Теперь сигнал CS становится неактивным только после каждого третьего байта.
Ручной режим управления сигналом выбора ведомого CS
Если требуется управлять сигналом CS вручную, например для того чтобы сигнал CS не устанавливался в неактивное состояние между посылками, то следует задать настройке ManualCS значение SPI_MANUALCS_ON. Функция SPI0_Init будет выглядеть так:
Управлять состоянием вывода CS можно с помощью функций HAL_SPI_CS_Enable и HAL_SPI_CS_Disable. Перед использованием HAL_SPI_CS_Enable следует включить модуль SPI функцией HAL_SPI_Enable. В конце передачи модуль SPI выключается функцией HAL_SPI_Disable.
Функция main: