Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Кармин Новиелло - Освоение STM32.pdf
Скачиваний:
2740
Добавлен:
23.09.2021
Размер:
47.68 Mб
Скачать

Универсальные асинхронные последовательные средства связи

216

8.2.1.Конфигурация UART с использованием CubeMX

Как уже было сказано, при первой конфигурации USART2 для нашей Nucleo лучше всего использовать CubeMX. Первым шагом является разрешение периферийного устройства USART2 в представлении Pinout, выбирая запись Asynchronous в выпадающем списке Mode, как показано на рисунке 5. Выводы PA2 и PA3 будут автоматически выделены зеленым цветом. Затем перейдите в раздел Configuration и нажмите кнопку USART2. Появится диалоговое окно конфигурации, как показано на рисунке 5 справа7. Оно позволяет нам конфигурировать параметры USART, такие как BaudRate, длину слова и так далее8.

После конфигурации интерфейса USART мы можем сгенерировать код Си. Вы заметите, что CubeMX помещает весь код инициализации USART2 в MX_USART2_UART_Init() (который содержится в файле main.c). И напротив, весь код, связанный с конфигурацией GPIO, помещается в функцию HAL_UART_MspInit(), которая находится в файле

stm32xxxx_hal_msp.c.

Рисунок 5: CubeMX можно использовать для облегчения конфигурации интерфейса UART2

8.3. UART-связь в режиме опроса

Микроконтроллеры STM32 и, следовательно, CubeHAL предоставляют три способа обмена данными между узлами по каналу связи UART: режимы опроса, прерываний и DMA. С этого момента важно подчеркнуть, что данные режимы представляют собой не только три разных варианта обращения с UART-связью. Это три разных программных подхода

7Обратите внимание, что на рисунке 5 представлено объединение двух скриншотов на одном рисунке. Невозможно отобразить диалоговое окно конфигурации USART из представления Pinout.

8Некоторые из вас, особенно те, у кого Nucleo-F3, заметят, что диалоговое окно конфигурации отличается от показанного на рисунке 5. Пожалуйста, обратитесь к справочному руководству по вашему целевому микроконтроллеру для получения дополнительной информации.

Универсальные асинхронные последовательные средства связи

217

к одной и той же задаче, которые дают несколько преимуществ как с точки зрения разработки, так и с точки зрения производительности. Позвольте кратко представить их.

В режиме опроса (polling mode), также называемом блокирующим режимом (blocking mode), основное приложение или один из его потоков синхронно ожидает передачу и прием данных. Это наиболее простая форма передачи данных с использованием данного периферийного устройства, и ее можно использовать, когда скорость передачи не слишком низкая, при этом UART не используется в качестве критически важного периферийного устройства в нашем приложении (классическим примером является использование UART в качестве консоли вывода при отладочной деятельности).

В режиме прерываний (interrupt mode), также называемом неблокирующим режимом

(non-blocking mode), основное приложение освобождается от ожидания завершения передачи и приема данных. Процедуры передачи данных завершаются, как только они завершают конфигурацию периферийного устройства. Когда передача данных заканчивается, последующее прерывание будет сигнализировать об этом основному коду. Данный режим больше подходит, когда скорость обмена данными низкая (ниже 38400 бит/с) или когда передача/прием происходят «изредка», по сравнению с другими действиями, выполняемыми микроконтроллером, и мы не хотим «застрять» на ожидании передачи данных.

Режим DMA обеспечивает наилучшую пропускную способность передачи благодаря прямому доступу периферийного устройства UART к внутренней памяти микроконтроллера. Данный режим лучше всего подходит для высокоскоростной связи, и когда мы полностью хотим освободить микроконтроллер от накладных расходов при передаче данных. Без режима DMA практически невозможно достичь самых высоких скоростей передачи данных, которые способны обрабатывать периферийные устройства USART. В данной главе мы не увидим этот режим USART-связи, оставив его следующей главе, посвященной управлению DMA.

Для передачи последовательности байтов по USART в режиме опроса HAL предоставляет функцию

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

где:

huart: это указатель на экземпляр структуры UART_HandleTypeDef, рассмотренной

нами ранее, который идентифицирует и конфигурирует периферийное устрой-

ство UART;

pData: указатель на массив, длина которого равна параметру Size, содержащий

последовательность байтов, которые мы собираемся передать;

Timeout: максимальное время, выраженное в миллисекундах, в течение которого

мы будем ждать завершения передачи. Если передача не завершается в течение заданного времени ожидания, функция прерывает свое выполнение и возвращает значение HAL_TIMEOUT; в противном случае она возвращает значение HAL_OK, если не возникает других ошибок. Кроме того, мы можем передать тайм-аут, равный HAL_MAX_DELAY (0xFFFF FFFF), чтобы неопределенно долго ждать завершения передачи.

Универсальные асинхронные последовательные средства связи

218

И наоборот, для получения последовательности байтов по USART в режиме опроса HAL предоставляет функцию

HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

где:

huart: это указатель на экземпляр структуры UART_HandleTypeDef, рассмотренной

нами ранее, который идентифицирует и конфигурирует периферийное устрой-

ство UART;

pData: указатель на массив, длина которого по крайней мере равна параметру Size, содержащий последовательность байтов, которую мы собираемся получить.

Функция будет блокироваться, пока не будут получены все байты, указанные параметром Size.

Timeout: максимальное время, выраженное в миллисекундах, а течение которого

мы будем ждать завершения приема. Если передача не завершается в течение заданного времени ожидания, функция прерывает свое выполнение и возвращает значение HAL_TIMEOUT; в противном случае она возвращает значение HAL_OK, если не возникает других ошибок. Кроме того, мы можем передать тайм-аут, равный HAL_MAX_DELAY (0xFFFF FFFF), чтобы неопределенно долго ждать завершения получения.

Прочитайте внимательно

Важно отметить, что механизм тайм-аута, предлагаемый двумя функциями, работает только в том случае, если процедура HAL_IncTick() вызывается каждые 1 мс, как это делается с помощью кода, генерируемого CubeMX (эта процедура увеличивает счетчик тиков HAL и вызывается внутри ISR таймера SysTick).

Хорошо. Теперь самое время увидеть пример.

Имя файла: src/main-ex1.c

21int main(void) {

22uint8_t opt = 0;

24/* Сброс всей периферии, Инициализация интерфейса Flash-памяти и SysTick. */

25

HAL_Init();

26

 

27/* Конфигурирование системного тактового сигнала */

28SystemClock_Config();

29

30/* Инициализация всей сконфигурированной периферии */

31MX_GPIO_Init();

32MX_USART2_UART_Init();

33

34 printMessage:

35

36 printWelcomeMessage();

37

Универсальные асинхронные последовательные средства связи

219

38while (1) {

39opt = readUserInput();

40processUserInput(opt);

41if(opt == 3)

42goto printMessage;

43}

44}

46void printWelcomeMessage(void) {

47HAL_UART_Transmit(&huart2, (uint8_t*)"\033[0;0H", strlen("\033[0;0H"), HAL_MAX_DELAY);

48HAL_UART_Transmit(&huart2, (uint8_t*)"\033[2J", strlen("\033[2J"), HAL_MAX_DELAY);

49HAL_UART_Transmit(&huart2, (uint8_t*)WELCOME_MSG, strlen(WELCOME_MSG), HAL_MAX_DELAY);

50HAL_UART_Transmit(&huart2, (uint8_t*)MAIN_MENU, strlen(MAIN_MENU), HAL_MAX_DELAY);

51}

53uint8_t readUserInput(void) {

54char readBuf[1];

56HAL_UART_Transmit(&huart2, (uint8_t*)PROMPT, strlen(PROMPT), HAL_MAX_DELAY);

57HAL_UART_Receive(&huart2, (uint8_t*)readBuf, 1, HAL_MAX_DELAY);

58return atoi(readBuf);

59}

61uint8_t processUserInput(uint8_t opt) {

62char msg[30];

64if(!opt || opt > 3)

65return 0;

67sprintf(msg, "%d", opt);

68HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);

70switch(opt) {

71case 1:

72HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);

73break;

74case 2:

75sprintf(msg, "\r\nUSER BUTTON status: %s",

76HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET ? "PRESSED" : "RELEASED");

77HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);

78break;

79case 3:

80return 2;

81};

82

83return 1;

84}

Данный пример – своего рода консоль управления. Приложение начинает печатать приветственное сообщение (строка 36), а затем входит в цикл, ожидая выбора пользователя.